diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 0000000..c47c9a9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,88 @@ +name: Bug Report +description: Create a report to help us improve +body: + - type: textarea + id: description + attributes: + label: Describe the bug + description: A clear and concise description of what the bug is. + validations: + required: true + - type: textarea + id: repro + attributes: + label: Steps To Reproduce + description: How do you trigger this bug? Please walk us through it step by step. + value: | + Steps to reproduce the behavior: + 1. Go to '...' + 2. Click on '....' + 3. Scroll down to '....' + 4. See error + render: typescript + validations: + required: true + - type: textarea + id: behavior + attributes: + label: Expected behavior + description: A clear and concise description of what you expected to happen. + validations: + required: true + - type: input + id: clickstream-version + attributes: + label: ClickstreamAnalytic React Native SDK Version + placeholder: e.g. 1.0.0 + validations: + required: true + - type: input + id: react-native-version + attributes: + label: React Native version + placeholder: e.g. 0.73.5 + validations: + required: true + - type: input + id: platform + attributes: + label: The platform of the bug + placeholder: | + - e.g. Android/iOS/All + validations: + required: true + - type: textarea + id: logs + attributes: + label: Relevant log output + description: >- + Include any relevant log output + value: | +
+ Log Messages + + ``` + INSERT LOG MESSAGES HERE + ``` +
+ render: shell + - type: dropdown + id: regression + attributes: + label: Is this a regression? + multiple: false + options: + - "Yes" + - "No" + validations: + required: true + - type: textarea + id: regression-info + attributes: + label: Regression additional context + placeholder: If it was a regression provide the versions used before and after the upgrade. + - type: textarea + id: context + attributes: + label: Additional context + description: Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml new file mode 100644 index 0000000..36105ac --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -0,0 +1,32 @@ +name: Feature request +description: Suggest an idea for this project +body: + - type: textarea + id: description + attributes: + label: Is your feature request related to a problem? Please describe. + description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + validations: + required: true + + - type: textarea + id: proposal + attributes: + label: Describe the solution you'd like + description: A clear and concise description of what you want to happen. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Describe alternatives you've considered + description: A clear and concise description of any alternative solutions or features you've considered. + validations: + required: true + + - type: textarea + id: context + attributes: + label: Additional context + description: Add any other context about the problem here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..5503089 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,16 @@ +## Issue \# + + +## Description + + +## General Checklist + + +- [ ] Added new tests to cover change, if needed +- [ ] Security oriented best practices and standards are followed (e.g. using input sanitization, principle of least privilege, etc) +- [ ] Documentation update for the change if required +- [ ] PR title conforms to conventional commit style +- [ ] If breaking change, documentation/changelog update with migration instructions + +By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml deleted file mode 100644 index fb98c79..0000000 --- a/.github/actions/setup/action.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Setup -description: Setup Node.js and install dependencies - -runs: - using: composite - steps: - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version-file: .nvmrc - - - name: Cache dependencies - id: yarn-cache - uses: actions/cache@v3 - with: - path: | - **/node_modules - .yarn/install-state.gz - key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ hashFiles('**/package.json', '!node_modules/**') }} - restore-keys: | - ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} - ${{ runner.os }}-yarn- - - - name: Install dependencies - if: steps.yarn-cache.outputs.cache-hit != 'true' - run: yarn install --immutable - shell: bash diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..50154fe --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,11 @@ +changelog: + categories: + - title: Feature + labels: + - enhancement + - title: Fix + labels: + - bug + - title: Other Changes + labels: + - "*" \ No newline at end of file diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml new file mode 100644 index 0000000..b241437 --- /dev/null +++ b/.github/workflows/build-android.yml @@ -0,0 +1,22 @@ +name: React Native SDK Build for Android + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build-android: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 + with: + distribution: 'corretto' + java-version: '17' + - name: Run build apk + run: | + yarn + cd example/android + ./gradlew assembleDebug diff --git a/.github/workflows/build-ios.yml b/.github/workflows/build-ios.yml new file mode 100644 index 0000000..e06779e --- /dev/null +++ b/.github/workflows/build-ios.yml @@ -0,0 +1,22 @@ +name: React Native SDK Build for iOS + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build-ios: + runs-on: macos-13-xl + steps: + - uses: actions/checkout@v3 + - name: Initialize submodules + run: | + git submodule update --init + - name: Run build ios + run: | + yarn + cd example/ios + pod install + xcodebuild -workspace ClickstreamReactNativeExample.xcworkspace -scheme ClickstreamReactNativeExample -configuration Debug -sdk iphonesimulator diff --git a/.github/workflows/build-rn.yml b/.github/workflows/build-rn.yml new file mode 100644 index 0000000..14767c8 --- /dev/null +++ b/.github/workflows/build-rn.yml @@ -0,0 +1,17 @@ +name: React Native SDK Build + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build-rn: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Run build + run: | + yarn + yarn run build diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 6297ef1..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,154 +0,0 @@ -name: CI -on: - push: - branches: - - main - pull_request: - branches: - - main - -jobs: - lint: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup - uses: ./.github/actions/setup - - - name: Lint files - run: yarn lint - - - name: Typecheck files - run: yarn typecheck - - test: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup - uses: ./.github/actions/setup - - - name: Run unit tests - run: yarn test --maxWorkers=2 --coverage - - build-library: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup - uses: ./.github/actions/setup - - - name: Build package - run: yarn prepare - - build-android: - runs-on: ubuntu-latest - env: - TURBO_CACHE_DIR: .turbo/android - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup - uses: ./.github/actions/setup - - - name: Cache turborepo for Android - uses: actions/cache@v3 - with: - path: ${{ env.TURBO_CACHE_DIR }} - key: ${{ runner.os }}-turborepo-android-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-turborepo-android- - - - name: Check turborepo cache for Android - run: | - TURBO_CACHE_STATUS=$(node -p "($(yarn turbo run build:android --cache-dir="${{ env.TURBO_CACHE_DIR }}" --dry=json)).tasks.find(t => t.task === 'build:android').cache.status") - - if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then - echo "turbo_cache_hit=1" >> $GITHUB_ENV - fi - - - name: Install JDK - if: env.turbo_cache_hit != 1 - uses: actions/setup-java@v3 - with: - distribution: 'zulu' - java-version: '17' - - - name: Finalize Android SDK - if: env.turbo_cache_hit != 1 - run: | - /bin/bash -c "yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses > /dev/null" - - - name: Cache Gradle - if: env.turbo_cache_hit != 1 - uses: actions/cache@v3 - with: - path: | - ~/.gradle/wrapper - ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('example/android/gradle/wrapper/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - - name: Build example for Android - env: - JAVA_OPTS: "-XX:MaxHeapSize=6g" - run: | - yarn turbo run build:android --cache-dir="${{ env.TURBO_CACHE_DIR }}" - - build-ios: - runs-on: macos-14 - env: - TURBO_CACHE_DIR: .turbo/ios - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup - uses: ./.github/actions/setup - - - name: Cache turborepo for iOS - uses: actions/cache@v3 - with: - path: ${{ env.TURBO_CACHE_DIR }} - key: ${{ runner.os }}-turborepo-ios-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-turborepo-ios- - - - name: Check turborepo cache for iOS - run: | - TURBO_CACHE_STATUS=$(node -p "($(yarn turbo run build:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}" --dry=json)).tasks.find(t => t.task === 'build:ios').cache.status") - - if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then - echo "turbo_cache_hit=1" >> $GITHUB_ENV - fi - - - name: Cache cocoapods - if: env.turbo_cache_hit != 1 - id: cocoapods-cache - uses: actions/cache@v3 - with: - path: | - **/ios/Pods - key: ${{ runner.os }}-cocoapods-${{ hashFiles('example/ios/Podfile.lock') }} - restore-keys: | - ${{ runner.os }}-cocoapods- - - - name: Install cocoapods - if: env.turbo_cache_hit != 1 && steps.cocoapods-cache.outputs.cache-hit != 'true' - run: | - cd example/ios - pod install - env: - NO_FLIPPER: 1 - - - name: Build example for iOS - run: | - yarn turbo run build:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}" diff --git a/.github/workflows/code-lint.yml b/.github/workflows/code-lint.yml new file mode 100644 index 0000000..6d92fe9 --- /dev/null +++ b/.github/workflows/code-lint.yml @@ -0,0 +1,19 @@ +name: React Native SDK Lint + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + code-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Run package install + run: yarn + - name: Run code format + run: yarn run format + - name: Run code lint + run: yarn run lint diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..d6ca881 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,45 @@ +name: Release Next Version +on: + workflow_dispatch: + inputs: + release_tag: + description: 'Release Tag' + required: true + type: string +env: + NEW_VERSION: ${{ github.event.inputs.release_tag }} +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + ref: main + fetch-depth: 0 + token: ${{ secrets.PROJECT_TOKEN }} + - name: Modify for next release + run: | + chmod +x release.sh + ./release.sh ${{ env.NEW_VERSION }} + yarn + git diff + git config user.name '${{ vars.USER_NAME }}' + git config user.email '${{ vars.USER_EMAIL }}' + git add . + git commit -m 'release: clickstream React Native ${{ env.NEW_VERSION }}' + git push + git tag v${{ env.NEW_VERSION }} + git push origin v${{ env.NEW_VERSION }} + - name: Prepare release file + run: | + yarn + yarn run pack + - name: Create GitHub release + uses: softprops/action-gh-release@v1 + with: + name: "Clickstream React Native ${{ env.NEW_VERSION }}" + files: | + *.tgz + tag_name: "v${{ env.NEW_VERSION }}" + prerelease: true + generate_release_notes: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..bf95dbc --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,22 @@ +name: React Native SDK Test + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + code-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Run test + run: | + yarn + yarn run test + - name: Upload Test Report + uses: codecov/codecov-action@v3 + with: + name: report + files: coverage/coverage-final.json diff --git a/.github/workflows/title-lint.yml b/.github/workflows/title-lint.yml new file mode 100644 index 0000000..d5f6cee --- /dev/null +++ b/.github/workflows/title-lint.yml @@ -0,0 +1,24 @@ +name: Pull Request Title Lint + +on: + pull_request: + branches: [ "*" ] + +jobs: + title-lint: + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + types: |- + feat + fix + chore + docs + ci + tests + requireScope: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 046d91e..dbfb5a1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -41,7 +41,8 @@ GitHub provides additional document on [forking a repository](https://help.githu ## Development workflow -This project is a monorepo managed using [Yarn workspaces](https://yarnpkg.com/features/workspaces). It contains the following packages: +This project is a monorepo managed using [Yarn workspaces](https://yarnpkg.com/features/workspaces). It contains the +following packages: - The library package in the root directory. - An example app in the `example/` directory. @@ -56,11 +57,17 @@ yarn The [example app](/example/) demonstrates usage of the library. You need to run it to test any changes you make. -It is configured to use the local version of the library, so any changes you make to the library's source code will be reflected in the example app. Changes to the library's JavaScript code will be reflected in the example app without a rebuild, but native code changes will require a rebuild of the example app. +It is configured to use the local version of the library, so any changes you make to the library's source code will be +reflected in the example app. Changes to the library's JavaScript code will be reflected in the example app without a +rebuild, but native code changes will require a rebuild of the example app. -If you want to use Android Studio or XCode to edit the native code, you can open the `example/android` or `example/ios` directories respectively in those editors. To edit the Objective-C or Swift files, open `example/ios/ClickstreamReactNativeExample.xcworkspace` in XCode and find the source files at `Pods > Development Pods > clickstream-react-native`. +If you want to use Android Studio or XCode to edit the native code, you can open the `example/android` or `example/ios` +directories respectively in those editors. To edit the Objective-C or Swift files, +open `example/ios/ClickstreamReactNativeExample.xcworkspace` in XCode and find the source files +at `Pods > Development Pods > clickstream-react-native`. -To edit the Java or Kotlin files, open `example/android` in Android studio and find the source files at `clickstream-react-native` under `Android`. +To edit the Java or Kotlin files, open `example/android` in Android studio and find the source files +at `clickstream-react-native` under `Android`. You can use various commands from the root directory to work with the project. @@ -85,8 +92,8 @@ yarn example ios Make sure your code passes TypeScript and ESLint. Run the following to verify: ```sh -yarn typecheck -yarn lint +yarn run format +yarn run lint ``` To fix formatting errors, run the following: @@ -98,7 +105,7 @@ yarn lint --fix Remember to add tests for your change if possible. Run the unit tests by: ```sh -yarn test +yarn run test ``` ### Commit message rules @@ -115,31 +122,21 @@ Please follow our commit messages rules: [ESLint](https://eslint.org/), [Prettier](https://prettier.io/), [TypeScript](https://www.typescriptlang.org/) -We use [TypeScript](https://www.typescriptlang.org/) for type checking, [ESLint](https://eslint.org/) with [Prettier](https://prettier.io/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing. +We use [TypeScript](https://www.typescriptlang.org/) for type checking, [ESLint](https://eslint.org/) +with [Prettier](https://prettier.io/) for linting and formatting the code, and [Jest](https://jestjs.io/) for testing. ### Scripts The `package.json` file contains various scripts for common tasks: - `yarn`: setup project by installing dependencies. -- `yarn typecheck`: type-check files with TypeScript. -- `yarn lint`: lint files with ESLint. -- `yarn test`: run unit tests with Jest. +- `yarn run format`: code format check for TypeScript. +- `yarn run lint`: lint files with ESLint. +- `yarn run test`: run unit tests with Jest. - `yarn example start`: start the Metro server for the example app. - `yarn example android`: run the example app on Android. - `yarn example ios`: run the example app on iOS. -### Sending a pull request - -> **Working on your first pull request?** You can learn how from this _free_ series: [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github). - -When you're sending a pull request: - -- Prefer small pull requests focused on one change. -- Verify that linters and tests are passing. -- Review the documentation to make sure it looks good. -- Follow the pull request template when opening a pull request. -- For pull requests that change the API or implementation, discuss with maintainers first by opening an issue. ## Finding contributions to work on Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. diff --git a/README.md b/README.md index 7541782..4afaae9 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,319 @@ -# clickstream-react-native +# AWS Solution Clickstream Analytics SDK for React Native -ClickstreamAnalytics React Native SDK +## Introduction -## Installation +Clickstream React Native SDK can help you easily collect and report events from React Native apps to AWS. This SDK is +part of an AWS solution - [Clickstream Analytics on AWS](https://github.com/awslabs/clickstream-analytics-on-aws), which +provisions data pipeline to ingest and process event data into AWS services such as S3, Redshift. -```sh -npm install clickstream-react-native +The SDK relies on the [Clickstream Android SDK](https://github.com/awslabs/clickstream-android) +and [Clickstream Swift SDK](https://github.com/awslabs/clickstream-swift). Therefore, Clickstream React Native SDK also +supports automatically collect common preset events and attributes (e.g., session start, first open). In addition, we've +added easy-to-use APIs to simplify data collection in React Native apps. + +Visit +our [Documentation site](https://awslabs.github.io/clickstream-analytics-on-aws/en/latest/sdk-manual/react-native/) to +learn more about Clickstream React Native SDK. + +### Platform Support + +**Android**: Supports Android 4.1 (API level 16) and later. + +**iOS**: Supports iOS 13 and later. + +## Integrate SDK + +### Include SDK + +```bash +npm install @aws/clickstream-react-native +``` + +After complete, you need to install the pod dependencies for iOS: + +```bash +cd ios && pod install +``` + +### Initialize the SDK + +Copy your configuration code from your clickstream solution web console, we recommended you add the code to your app's +entry point like `index.js`, the configuration code should look like as follows. You can also manually add this code +snippet and replace the values of appId and endpoint after you registered app to a data pipeline in the Clickstream +Analytics solution web console. + +```javascript +// index.js + +import { ClickstreamAnalytics } from '@aws/clickstream-react-native'; + +ClickstreamAnalytics.init({ + appId: 'your appId', + endpoint: 'https://example.com/collect', +}); +``` + +Your `appId` and `endpoint` are already set up in it. + +> Make sure you call `ClickstreamAnalytics.init` as early as possible in your application’s life-cycle. And make sure +> the SDK is initialized when calling other APIs. + +### Start using + +#### Record events + +Add the following code where you need to record events. + +```typescript +import { ClickstreamAnalytics } from '@aws/clickstream-react-native'; + +// record event with attributes +ClickstreamAnalytics.record({ + name: 'button_click', + attributes: { + event_category: 'shoes', + currency: 'CNY', + value: 279.9, + }, +}); + +// record event with name +ClickstreamAnalytics.record({ name: 'button_click' }); +``` + +#### Login and logout + +```typescript +import { ClickstreamAnalytics } from '@aws/clickstream-react-native'; + +// when user login success. +ClickstreamAnalytics.setUserId("userId"); + +// when user logout +ClickstreamAnalytics.setUserId(null); ``` -## Usage +#### Add user attributes -```js -import { ClickstreamAnalytics } from 'clickstream-react-native'; +```typescript +import { ClickstreamAnalytics } from '@aws/clickstream-react-native'; -const result = await ClickstreamAnalytics.configure({ - appId: 'your appId', - endpoint: 'your endpoint', +ClickstreamAnalytics.setUserAttributes({ + userName: "carl", + userAge: 22 }); ``` -## Contributing +When opening the Apps for the first time after integrating the SDK, you need to manually set the user attributes once, +and current login user's attributes will be cached in disk, so the next time app open you don't need to set all user +attributes again, of course you can use the same API `ClickstreamAnalytics.setUserAttributes()` to update the current +user's attribute when it changes. + +#### Add global attributes + +1. Add global attributes when initializing the SDK + + ```typescript + ClickstreamAnalytics.init({ + appId: "your appId", + endpoint: "https://example.com/collect", + globalAttributes:{ + _traffic_source_medium: "Search engine", + _traffic_source_name: "Summer promotion", + } + }); + ``` + +2. Add global attributes after initializing the SDK + + ``` typescript + ClickstreamAnalytics.setGlobalAttributes({ + _traffic_source_medium: "Search engine", + level: 10, + }); + ``` + +It is recommended to set global attributes when initializing the SDK, global attributes will be included in all events +that occur after it is set. + +#### Delete global attributes + +``` typescript +ClickstreamAnalytics.deleteGlobalAttributes(['level','_traffic_source_medium']); +``` + +#### Record event with items + +You can add the following code to log an event with an item. + +**Note: Only pipelines from version 1.1+ can handle items with custom attribute.** + +```typescript +import { ClickstreamAnalytics, Item } from '@aws/clickstream-react-native'; + +const itemBook: Item = { + id: '123', + name: 'Nature', + category: 'book', + price: 99, + book_publisher: "Nature Research", +}; +ClickstreamAnalytics.record({ + name: 'view_item', + attributes: { + currency: 'USD', + event_category: 'recommended', + }, + items: [itemBook], +}); +``` + +#### Record Screen View events manually + +By default, SDK will automatically track the preset `_screen_view` event when Android Activity triggers `onResume` or +iOS ViewController triggers `viewDidAppear`. + +You can also manually record screen view events whether automatic screen view tracking is enabled, add the following +code to record a screen view event with two attributes. + +* `SCREEN_NAME` Required. Your screen's name. +* `SCREEN_UNIQUE_ID` Optional. Set the id of your Component. If you do not set, the SDK will set a default value based + on the hashcode of the current Activity or ViewController. + +```typescript +import { ClickstreamAnalytics } from '@aws/clickstream-react-native'; + +ClickstreamAnalytics.record({ + name: ClickstreamAnalytics.Event.SCREEN_VIEW, + attributes: { + [ClickstreamAnalytics.Attr.SCREEN_NAME]: 'HomeComponet', + [ClickstreamAnalytics.Attr.SCREEN_UNIQUE_ID]: '123adf', + }, +}); +``` + +#### Other configurations + +In addition to the required `appId` and `endpoint`, you can configure other information to get more customized usage +when initialing the SDK: + +```typescript +import { ClickstreamAnalytics } from '@aws/clickstream-react-native'; + +ClickstreamAnalytics.init({ + appId: 'your appId', + endpoint: 'https://example.com/collect', + isLogEvents: true, + isCompressEvents: true, + isTrackScreenViewEvents: false, + isTrackUserEngagementEvents: true, + isTrackAppExceptionEvents: true, + sendEventsInterval: 15000, + sessionTimeoutDuration: 1800000, + authCookie: 'your auth cookie', + globalAttributes: { + _traffic_source_medium: 'Search engine', + }, +}); +``` + +Here is an explanation of each property: + +- **appId (Required)**: the app id of your project in solution web control. +- **endpoint (Required)**: the endpoint path you will upload the event to ingestion server. +- **isLogEvents**: whether to print out event json for debugging, default is `false`. +- **isCompressEvents**: whether to compress event content when uploading events, default is `true`. +- **sendEventsInterval**: event sending interval millisecond, works only bath send mode, the default value is `5000` +- **isTrackScreenViewEvents**: whether auto record native screen view events, default is `true` +- **isTrackUserEngagementEvents**: whether auto record user engagement events, default is `true` +- **isTrackAppExceptionEvents**: whether auto record exception events of native apps, default is `false` +- **sendEventsInterval**: event sending interval millisecond, the default value is `10000` (10s) +- **sessionTimeoutDuration**: the duration for session timeout millisecond, default is `1800000` (30 minutes) +- **authCookie**: your auth cookie for AWS application load balancer auth cookie. +- **globalAttributes**: the global attributes when initializing the SDK. + +#### Configuration update + +You can update the default configuration after initializing the SDK, below are the additional configuration options you +can customize. + +```typescript +import { ClickstreamAnalytics } from '@aws/clickstream-react-native'; + +ClickstreamAnalytics.updateConfigure({ + appId: 'your appId', + endpoint: 'https://example.com/collect', + isLogEvents: true, + authCookie: 'your auth cookie', + isCompressEvents: true, + isTrackPageViewEvents: false, + isTrackUserEngagementEvents: false, + isTrackAppExceptionEvents: false, +}); +``` + +#### Logging events json in debug mode + +```javascript +import { ClickstreamAnalytics } from '@aws/clickstream-react-native'; + +ClickstreamAnalytics.init({ + appId: 'your appId', + endpoint: 'https://example.com/collect', + isLogEvents: true, +}); +``` + +After configuring `isLogEvents:true` when initializing the SDK, when you record an event, you can see the event raw json +in AndroidStudio Logcat or Xcode debug console by filter `EventRecorder`. + +#### Disable SDK + +You can disable the SDK in the scenario you need. After disabling the SDK, the SDK will not handle the logging and +sending of any events. Of course, you can enable the SDK when you need to continue logging events. + +```javascript +import { ClickstreamAnalytics } from '@aws/clickstream-react-native'; + +// disable SDK +ClickstreamAnalytics.disable(); + +// enable SDK +ClickstreamAnalytics.enable(); +``` + +## How to integrate and test locally + +Clone this repository locally and execute the following script to generate `clickstream-react-native-0.1.0.tgz` zip +package, which will be located in the project root folder. + +```bash +cd clickstream-react-native && yarn && yarn run pack +``` + +Copy the `clickstream-react-native-0.1.0.tgz` into your project, then execute the script in your project root folder to +install the SDK. + +```bash +yarn add ./clickstream-react-native-0.1.0.tgz +``` + +**Note**: Please correct the SDK version and change the path to where the `clickstream-react-native-0.1.0.tgz` file is +located. + +You can also find the `clickstream-react-native-0.1.0.tgz` file in +the [Release](https://github.com/awslabs/clickstream-react-native/releases) page. + +### Test + +```bash +yarn run test +``` + +## Security -See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. +See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. ## License -Apache-2.0 +This library is licensed under the [Apache 2.0 License](./LICENSE). diff --git a/example/src/App.tsx b/example/src/App.tsx index f786371..330f9cd 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -7,7 +7,7 @@ import { ScrollView, SafeAreaView, } from 'react-native'; -import { ClickstreamAnalytics } from 'clickstream-react-native'; +import { ClickstreamAnalytics, Item } from 'clickstream-react-native'; export default function App() { const initSDK = async () => { @@ -45,7 +45,26 @@ export default function App() { }, }); }; + + const recordCustomScreenViewEvents = () => { + ClickstreamAnalytics.record({ + name: ClickstreamAnalytics.Event.SCREEN_VIEW, + attributes: { + [ClickstreamAnalytics.Attr.SCREEN_NAME]: 'HomeComponent', + [ClickstreamAnalytics.Attr.SCREEN_UNIQUE_ID]: '123adf', + }, + }); + }; + const recordEventWithItems = () => { + const item_shoes: Item = { + id: '1', + name: 'boy shoes', + brand: 'Nike', + currency: 'CNY', + category: 'shoes', + locationId: '1', + }; ClickstreamAnalytics.record({ name: 'product_view', attributes: { @@ -53,16 +72,7 @@ export default function App() { currency: 'CNY', price: 279.9, }, - items: [ - { - id: '1', - name: 'boy shoes', - brand: 'Nike', - currency: 'CNY', - category: 'shoes', - locationId: '1', - }, - ], + items: [item_shoes], }); }; const setUserId = () => { @@ -134,6 +144,10 @@ export default function App() { onPress={recordEventWithAttributes} /> + diff --git a/release.sh b/release.sh new file mode 100755 index 0000000..2aa5f56 --- /dev/null +++ b/release.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +version="$1" +echo ${version} +regex="[0-9]\+\.[0-9]\+\.[0-9]\+" + +sed -i "s/\"version\": \"${regex}\"/\"version\": \"${version}\"/g" package.json +sed -i "s/clickstream-react-native-${regex}.tgz/clickstream-react-native-${version}.tgz/g" README.md diff --git a/src/ClickstreamAnalytics.ts b/src/ClickstreamAnalytics.ts index 0b83a6d..d39f1e7 100644 --- a/src/ClickstreamAnalytics.ts +++ b/src/ClickstreamAnalytics.ts @@ -104,4 +104,13 @@ export class ClickstreamAnalytics { static isNotEmpty(obj: any): boolean { return obj !== undefined && obj !== null && Object.keys(obj).length > 0; } + + static readonly Event = { + SCREEN_VIEW: '_screen_view', + }; + + static readonly Attr = { + SCREEN_NAME: '_screen_name', + SCREEN_UNIQUE_ID: '_screen_unique_id', + }; } diff --git a/src/__tests__/ClickstreamAnalytics.test.ts b/src/__tests__/ClickstreamAnalytics.test.ts index d23b3c9..2a965e5 100644 --- a/src/__tests__/ClickstreamAnalytics.test.ts +++ b/src/__tests__/ClickstreamAnalytics.test.ts @@ -127,6 +127,25 @@ describe('ClickstreamAnalytics test', () => { ); }); + test('test record custom screen view events', () => { + ClickstreamAnalytics.record({ + name: ClickstreamAnalytics.Event.SCREEN_VIEW, + attributes: { + [ClickstreamAnalytics.Attr.SCREEN_NAME]: 'HomeComponent', + [ClickstreamAnalytics.Attr.SCREEN_UNIQUE_ID]: '123adf', + }, + }); + expect(NativeModules.ClickstreamReactNative.record).toHaveBeenCalledWith( + expect.objectContaining({ + name: ClickstreamAnalytics.Event.SCREEN_VIEW, + attributes: { + [ClickstreamAnalytics.Attr.SCREEN_NAME]: 'HomeComponent', + [ClickstreamAnalytics.Attr.SCREEN_UNIQUE_ID]: '123adf', + }, + }) + ); + }); + test('test record event with empty event name', () => { ClickstreamAnalytics.record({ name: '', diff --git a/src/index.ts b/src/index.ts index 2b28034..6c44b3b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,3 +12,4 @@ */ export { ClickstreamAnalytics } from './ClickstreamAnalytics'; +export { Item } from './types/Analytics';