@convivainc/conviva-react-native-appanalytics
Version:
Conviva React Native Application Analytics Library
818 lines (644 loc) • 27.6 kB
Markdown
# Conviva React Native App Analytics - Developer Integration Guide
Use the Conviva React Native App Analytics SDK to auto-collect events and track application-specific events and state changes. The React Native bridges are internally built on top of the [Android](https://github.com/Conviva/conviva-android-appanalytics) and [iOS](https://github.com/Conviva/conviva-ios-appanalytics) native sensors.
**Table of Contents**
- [Quick Start](#quick-start)
- [More Features](#more-features)
- [Error Tracking](#error-tracking)
- [Auto-collected Events](#auto-collected-events)
- [FAQ](#faq)
---
## Quick Start
### Supported Platforms
| Platform | Minimum Version |
|---|---|
| Android | Android 5.0 (API level 21) |
| iOS / tvOS | iOS 9.0 / tvOS 9.0 |
| React Native | 0.60+ (auto-linking supported) |
| Expo bare workflow | Supported (requires native setup below) |
| Expo managed workflow | Run `npx expo prebuild` first to generate native folders |
### Expo Projects
**Bare workflow** (created with `expo init --template bare-minimum` or ejected): The `android/` and `ios/` folders exist. Follow all steps below as for standard React Native.
**Managed workflow** (created with `npx create-expo-app` without ejecting, no `android/` or `ios/` folders): Native folders must be generated before native setup is possible.
```bash
npx expo prebuild
```
After prebuild, the project behaves as Expo bare workflow. Complete all steps below.
Steps 1 (add to `package.json`), 5 (Babel plugin), and 6 (React Navigation setup) apply to both managed and bare Expo workflows regardless of prebuild status.
### 1. Add the npm Package to `package.json`
> **Do not run `npm install` / `yarn add` for this package in isolation.** Instead, add the entries to `package.json` manually and run the install command once after all edits are complete.
Add to `dependencies` in `package.json`:
```json
"@convivainc/conviva-react-native-appanalytics": "<version>"
```
Then run the install command from the project root (use whichever matches your project):
```bash
npm install
```
```bash
yarn
```
After installing, run pod install for iOS:
```bash
npx pod-install
```
### 2. Android Native Setup
#### 2a. Determine Your App Type
Before adding the tracker dependency, identify whether your Android app is **standard React Native** or **hybrid**:
| App Type | Description |
|---|---|
| **Standard React Native** | All screens are React Native. The only Activity is `MainActivity` extending `ReactActivity`. No native Android Activities outside the RN bridge. |
| **Hybrid** | Contains native Android Activities (Java/Kotlin) that run outside the React Native bridge -- for example, a native splash screen, login screen, or settings activity. |
**Standard React Native apps:** The React Native bridge initializes the tracker automatically when you call `createTracker(...)` in JavaScript (Step 4). You do not need to add the tracker dependency or call `createTracker` natively. Skip ahead to [Step 2b](#2b-add-the-gradle-plugin-for-button-click-and-network-request-auto-collection).
**Hybrid apps with multiple Activities:** The tracker must also be initialized natively so that native Activities are tracked from app start, before the React Native bridge loads. Continue with the steps below.
#### Add the Tracker Dependency (Hybrid Apps only)
In `android/app/build.gradle`, add to `dependencies {}`:
```groovy
dependencies {
// ...
implementation 'com.conviva.sdk:conviva-android-tracker:<ANDROID_TRACKER_VERSION>'
}
```
> **Important:** `<ANDROID_TRACKER_VERSION>` is the version of the Android native tracker artifact -- it is **independent of the npm package version** (`CONVIVA_RN_VERSION`). Find the correct version at [GitHub Releases](https://github.com/Conviva/conviva-android-appanalytics/releases). Do not use the npm version number here.
#### Initialize the Native Tracker (Hybrid Apps only)
After adding the dependency, initialize the tracker in your Android `Application` class's `onCreate()`. This ensures all native Activities are covered from app start.
**Find your Application class:** Check the `android:name` attribute on the `<application>` tag in `android/app/src/main/AndroidManifest.xml`. If no custom Application class exists, use the MAIN/LAUNCHER Activity.
**Java:**
```java
// Exception is java.lang.Exception — auto-imported in every Java file, no import statement needed
import com.conviva.apptracker.ConvivaAppAnalytics;
import com.conviva.apptracker.controller.TrackerController;
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
try {
TrackerController tracker = ConvivaAppAnalytics.createTracker(this, "YOUR_CUSTOMER_KEY", "YOUR_APP_NAME");
if (tracker == null) {
// handle initialization failure
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
```
**Kotlin:**
```kotlin
// Exception is kotlin.Exception — auto-imported in every Kotlin file, no import statement needed
import com.conviva.apptracker.ConvivaAppAnalytics
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
try {
val tracker = ConvivaAppAnalytics.createTracker(this, "YOUR_CUSTOMER_KEY", "YOUR_APP_NAME")
if (tracker == null) {
// handle initialization failure
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
```
> Use the same `YOUR_CUSTOMER_KEY` and `YOUR_APP_NAME` values as in your JavaScript `createTracker(...)` call (Step 4). Do not hardcode these -- they must match exactly.
>
> Do not create a new `Application` class if one does not exist -- ask your developer to create one, or use the MAIN/LAUNCHER Activity.
#### 2b. Add the Gradle Plugin (for button click and network request auto-collection)
**For Android Gradle Plugin (AGP) >= 8.0 - use plugin version 0.3.x:**
In the **root** `android/build.gradle`:
```groovy
buildscript {
dependencies {
// ...
classpath 'com.conviva.sdk:android-plugin:0.3.x'
}
}
```
**For AGP below 8.0 - use plugin version 0.2.x:**
In the **root** `android/build.gradle`:
```groovy
buildscript {
dependencies {
// ...
classpath 'com.conviva.sdk:android-plugin:0.2.x'
}
}
```
In `android/app/build.gradle`, apply the plugin at the end of the plugins section:
```groovy
apply plugin: 'com.conviva.sdk.android-plugin'
```
Or in Kotlin DSL (`android/app/build.gradle.kts`):
```kotlin
plugins {
// ...
id("com.conviva.sdk.android-plugin")
}
```
#### 2c. ProGuard / R8 Rules
Append to `android/app/proguard-rules.pro`:
```proguard
-keepnames class * extends android.view.View
-keep,allowshrinking class com.conviva.** { *; }
```
### 3. iOS Native Setup
The `ConvivaAppAnalytics` pod is automatically resolved via `RNConvivaAppAnalytics.podspec` when `npx pod-install` runs. No manual Podfile changes are needed.
Verify that `ios/Podfile` has `platform :ios, '9.0'` or higher.
#### Multi-SDK Runtime Stability (Info.plist)
If your app integrates multiple SDKs that use ISA-swizzling (e.g., analytics, crash reporting, or A/B testing SDKs), add the following key to `ios/<YourAppName>/Info.plist` to prevent runtime crashes:
```xml
<key>CATGeneratedClassDisposeDisabled</key>
<true/>
```
This setting causes the SDK to retain a small, predictable amount of class metadata in memory, which improves runtime stability when multiple swizzling SDKs are present.
### 4. Initialize the Tracker
Call `createTracker` once, at app startup, before any screen rendering. Place it at the top of your root component file (`App.js`, `App.tsx`, or `index.js`).
**JavaScript:**
```js
import { createTracker } from '@convivainc/conviva-react-native-appanalytics';
let tracker;
try {
tracker = createTracker('YOUR_CUSTOMER_KEY', 'YOUR_APP_NAME');
if (!tracker) {
console.error('Tracker initialization returned null');
}
} catch (error) {
console.error(error);
}
```
**TypeScript:**
```ts
import { createTracker, ReactNativeTracker } from '@convivainc/conviva-react-native-appanalytics';
let tracker: ReactNativeTracker | undefined;
try {
tracker = createTracker('YOUR_CUSTOMER_KEY', 'YOUR_APP_NAME');
if (!tracker) {
console.error('Tracker initialization returned null');
}
} catch (error) {
console.error(error);
}
```
> **YOUR_CUSTOMER_KEY** - A string to identify your Conviva account. Use separate keys for debug and production. Find your keys on the Pulse account info page.
> **YOUR_APP_NAME** - A string value that uniquely identifies your app across platforms.
### 5. Babel Plugin Setup (Button Clicks and `displayName` Auto-detection)
The required Babel configuration depends on your installed version of `@convivainc/conviva-react-native-appanalytics`. Check the version in your `package.json`.
#### For version <= 0.2.8
Add two separate plugins to your `babel.config.js` -- one for button click auto-detection and one for `displayName` injection:
**`babel.config.js`:**
```js
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
'./node_modules/@convivainc/conviva-react-native-appanalytics/instrumentation/index.js',
'add-react-displayname',
],
};
```
Add the following to `devDependencies` in `package.json`:
```json
"babel-plugin-add-react-displayname": "0.0.5",
"babel-types": "^6.26.0",
"babel-template": "^6.26.0"
```
- `babel-plugin-add-react-displayname` `0.0.5` is the final published version of the package.
- `babel-types` and `babel-template` at `^6.26.0` are required by `instrumentation/index.js`; they are legacy Babel 6 packages not installed automatically in Babel 7 projects.
Then run `npm install` (or `yarn`) from the project root.
#### For version >= 0.3.0
A single unified Conviva plugin handles both button click auto-detection and `displayName` injection. **No extra dependencies are needed in the app.**
**`babel.config.js`:**
```js
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
'@convivainc/conviva-react-native-appanalytics/plugin',
],
};
```
`displayName` auto-detection is absorbed internally by the Conviva plugin. Do **not** add `add-react-displayname`, `babel-plugin-add-react-displayname`, or `@babel/plugin-transform-react-display-name` to `plugins` or `devDependencies`.
---
After updating `babel.config.js`, restart Metro with `--reset-cache` (applies to both versions):
```bash
npx react-native start --reset-cache
```
The Conviva instrumentation plugin enables auto-detection of button clicks for: `Button`, `TouchableHighlight`, `TouchableOpacity`, `TouchableWithoutFeedback`, and `TouchableNativeFeedback` components.
### 6. React Navigation Setup (Screen View Auto-detection)
#### React Navigation >= 5
Wrap your `NavigationContainer` with `withReactNavigationAutotrack`. The original `NavigationContainer` import must remain -- it is passed to the HOC and used internally.
**JavaScript:**
```js
import { NavigationContainer } from '@react-navigation/native';
import {
withReactNavigationAutotrack,
autocaptureNavigationTrack,
} from '@convivainc/conviva-react-native-appanalytics';
let ConvivaNavigationContainer;
try {
ConvivaNavigationContainer =
withReactNavigationAutotrack(autocaptureNavigationTrack)(NavigationContainer);
if (!ConvivaNavigationContainer) {
console.error('Navigation container setup returned null');
}
} catch (error) {
console.error(error);
}
```
**TypeScript** -- add `as typeof NavigationContainer` to preserve prop types for JSX type-checking:
```ts
import { NavigationContainer } from '@react-navigation/native';
import {
withReactNavigationAutotrack,
autocaptureNavigationTrack,
} from '@convivainc/conviva-react-native-appanalytics';
let ConvivaNavigationContainer: typeof NavigationContainer | undefined;
try {
ConvivaNavigationContainer =
withReactNavigationAutotrack(autocaptureNavigationTrack)(NavigationContainer) as typeof NavigationContainer;
if (!ConvivaNavigationContainer) {
console.error('Navigation container setup returned null');
}
} catch (error) {
console.error(error);
}
export default function App() {
return (
<ConvivaNavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</ConvivaNavigationContainer>
);
}
```
#### React Navigation < 5
Wrap the `AppNavigator` (result of `createAppContainer()`) with `withReactNavigationAutotrack`:
```js
import { createStackNavigator, createAppContainer } from 'react-navigation';
import {
withReactNavigationAutotrack,
autocaptureNavigationTrack,
} from '@convivainc/conviva-react-native-appanalytics';
const AppNavigator = createAppContainer(
createStackNavigator(
{ Home: HomeScreen, Settings: SettingsScreen },
{ initialRouteName: 'Home' }
)
);
let App;
try {
App = withReactNavigationAutotrack(autocaptureNavigationTrack)(AppNavigator);
if (!App) {
console.error('Navigation app setup returned null');
}
} catch (error) {
console.error(error);
}
export default App;
```
---
## More Features
### Set the User ID (Viewer ID)
User ID is a unique string identifier to distinguish individual viewers. If using Conviva Video Sensor, match it with the Viewer ID. Use a non-PII identifier only (opaque provider UID, stored UUID, or backend account ID - never email or phone).
```js
try {
if (tracker != null) {
tracker.setSubjectData({ userId: 'your-non-pii-user-id' });
}
} catch (error) {
console.error(error);
}
```
Clear on logout:
```js
try {
if (tracker != null) {
tracker.setSubjectData({ userId: null });
}
} catch (error) {
console.error(error);
}
```
### Track Custom Events
Use `trackCustomEvent()` to track application-specific events.
| Parameter | Type | Description |
|---|---|---|
| `eventName` | `string` | Name of the custom event (mandatory) |
| `eventData` | `object` | Any JSON-serializable object |
```js
try {
if (tracker != null) {
tracker.trackCustomEvent('custom_event_name', {
tagKey1: 'tagValue1',
tagKey2: 100,
tagKey3: true,
});
}
} catch (error) {
console.error(error);
}
```
### Track Revenue Events (>= 0.2.8)
Use `trackRevenueEvent()` to track purchase and revenue events.
| Parameter | Type | Required | Description |
|---|---|---|---|
| `totalOrderAmount` | `number` | Yes | Total order amount |
| `transactionId` | `string` | Yes | Unique transaction identifier |
| `currency` | `string` | Yes | Currency code (e.g. `"USD"`) |
| `taxAmount` | `number` | No | Tax amount |
| `shippingCost` | `number` | No | Shipping cost |
| `discount` | `number` | No | Order-level discount amount |
| `cartSize` | `number` | No | Number of items in the cart |
| `paymentMethod` | `string` | No | Payment method used |
| `paymentProvider` | `string` | No | Payment provider name |
| `items` | `RevenueEventItemProps[]` | No | Array of purchased items |
| `extraMetadata` | `object` | No | Any additional key-value pairs |
Each item in `items` may include: `productId`, `name`, `sku`, `category`, `unitPrice`, `quantity`, `discount`, `brand`, `variant`, `extraMetadata`.
```js
try {
if (tracker != null) {
tracker.trackRevenueEvent({
totalOrderAmount: 49.99,
transactionId: 'txn-001',
currency: 'USD',
taxAmount: 4.50,
shippingCost: 5.99,
paymentMethod: 'credit_card',
items: [
{
productId: 'prod-123',
name: 'Widget',
unitPrice: 19.99,
quantity: 2,
},
],
});
}
} catch (error) {
console.error(error);
}
```
### Set / Clear Custom Tags
Custom tags are global key-value pairs attached to all subsequent events until cleared.
**Set tags:**
```js
try {
if (tracker != null) {
tracker.setCustomTags({
tagKey1: 'tagValue1',
tagKey2: 100,
tagKey3: true,
});
}
} catch (error) {
console.error(error);
}
```
**Set tags with category:**
```js
try {
if (tracker != null) {
tracker.setCustomTagsWithCategory('myCategory', {
tagKey1: 'tagValue1',
});
}
} catch (error) {
console.error(error);
}
```
**Clear specific tags:**
```js
try {
if (tracker != null) {
tracker.clearCustomTags(['tagKey1', 'tagKey2']);
}
} catch (error) {
console.error(error);
}
```
**Clear all tags:**
```js
try {
if (tracker != null) {
tracker.clearAllCustomTags();
}
} catch (error) {
console.error(error);
}
```
### Track Page View Events
Use `trackPageView()` to track in-app page navigations explicitly.
```js
try {
if (tracker != null) {
tracker.trackPageView({
pageUrl: 'https://example.com/home',
pageTitle: 'Home', // optional
referrer: 'https://example.com', // optional
});
}
} catch (error) {
console.error(error);
}
```
### WebView Event Bridge
To track events from web content rendered in `react-native-webview`:
```js
import { getWebViewCallback } from '@convivainc/conviva-react-native-appanalytics';
import { WebView } from 'react-native-webview';
let webViewCallback;
try {
webViewCallback = getWebViewCallback();
if (!webViewCallback) {
console.error('WebView callback setup returned null');
}
} catch (error) {
console.error(error);
}
<WebView
source={{ uri: 'https://your-web-app.com' }}
onMessage={webViewCallback}
/>
```
The web app must use the Conviva WebView tracker to send events.
### WebView Client ID Sync
> Available from React Native SDK [v0.4.0](https://github.com/Conviva/conviva-react-native-appanalytics/releases/tag/v0.4.0). Requires React Native 0.68+, [`react-native-webview`](https://github.com/react-native-webview/react-native-webview) v11+, and Android plugin [v0.3.9](https://github.com/Conviva/conviva-android-plugin/releases/tag/v0.3.9)+. JavaScript must be enabled in the WebView for this feature to work.
The SDK automatically shares the native client ID with in-app WebViews, linking native and web sessions to the same user. It uses two mechanisms:
- **Cookie (primary):** Seeds a `Conviva_sdkConfig` cookie into the WebView cookie jar per configured domain.
- **JS bridge (fallback):** Web SDK reads the native client ID from the injected bridge when the cookie is unavailable.
**Web SDK compatibility:** The cookie path works with any Web SDK version. The JS bridge fallback requires **Web SDK ≥ [2.2.0](https://github.com/Conviva/conviva-js-appanalytics/releases/tag/v2.2.0)**.
#### Integration Options
**Option 1 — Remote config only (no code changes required):** Both cookie seeding and JS bridge are enabled by default. Contact Conviva support to configure domains in remote config for your account.
**Option 2 — Supply fallback domains in app code:**
Pass a `clidSyncConfig` object as the third argument to `createTracker()`. App-config domains take effect immediately before the first remote config fetch; once remote config is received, its domain list replaces the app-config list.
**JavaScript:**
```js
import { createTracker } from '@convivainc/conviva-react-native-appanalytics';
let tracker;
try {
tracker = createTracker('YOUR_CUSTOMER_KEY', 'YOUR_APP_NAME', {
clidSyncConfig: {
webViewCookie: {
domains: ['.example.com', '.partner.com'], // use leading-dot for subdomain coverage
}
},
});
} catch (error) {
console.error(error);
}
```
**TypeScript:**
```ts
import { createTracker, ReactNativeTracker } from '@convivainc/conviva-react-native-appanalytics';
let tracker: ReactNativeTracker | undefined;
try {
tracker = createTracker('YOUR_CUSTOMER_KEY', 'YOUR_APP_NAME', {
clidSyncConfig: {
webViewCookie: {
domains: ['.example.com', '.partner.com'], // use leading-dot for subdomain coverage
}
},
});
} catch (error) {
console.error(error);
}
```
> Use leading-dot domains (`.example.com`) to cover all subdomains. Domains without a leading dot match only the exact host.
| Option | Type | Description |
|---|---|---|
| `webViewCookie.domains` | `string[]` | Domains that receive the `Conviva_sdkConfig` cookie. Use leading-dot form (`.example.com`). |
### Client ID
```js
import { getClientId, setClientId } from '@convivainc/conviva-react-native-appanalytics';
try {
const id = await getClientId();
if (id == null) {
console.error('getClientId returned null');
}
await setClientId('custom-client-id');
} catch (error) {
console.error(error);
}
```
### Error Tracking
> Available from React Native SDK v0.5.0.
The SDK captures JavaScript errors automatically once `createTracker(...)` runs — **no extra code is required**. The following are captured out of the box:
- **Uncaught errors** thrown anywhere in your JS (via a chained global error handler).
- **Unhandled promise rejections** (promises rejected with no `.catch()`).
- **Native fatal crashes**, deduplicated against the JS error stream.
Rate limiting is enabled by default to protect against error storms.
Error tracking is **on by default**. To disable it entirely, pass `errorTracking: false` as the third argument to `createTracker`: or via conviva remote config
```js
import { createTracker } from '@convivainc/conviva-react-native-appanalytics';
const tracker = createTracker('YOUR_CUSTOMER_KEY', 'YOUR_APP_NAME', {
errorTracking: false, // fully disable JS error capture
});
```
#### Configuration Options
Pass an `errorTracking` object to `createTracker` to customize capture. Every field is optional.
| Option | Type | Default | Description |
|---|---|---|---|
| `enabled` | `boolean` | `true` | Master switch for the error tracking module. |
| `captureGlobalErrors` | `boolean` | `true` | Capture uncaught errors via the global handler. |
| `captureUnhandledRejections` | `boolean` | `true` | Capture unhandled promise rejections. |
| `suppressInDev` | `boolean` | `false` | Skip capture while running in dev mode (`__DEV__`). |
| `enableRateLimiting` | `boolean` | `true` | Drop events once the per-window limit is exceeded. |
| `maxEventsPerWindow` | `number` | `20` | Max events captured per rate-limit window. |
| `rateLimitWindowMs` | `number` | `1000` | Rate-limit window length, in milliseconds. |
| `disconnectDurationMs` | `number` | `2000` | Cool-down after the limit is hit, in milliseconds. |
| `promiseRejectionsAsHandled` | `boolean` | `false` | Report unhandled rejections as handled (`warning`) instead of unhandled (`error`). |
| `bundleId` | `string` | — | JS bundle hash for symbolication of OTA-updated apps. |
| `beforeCapture` | `(payload) => boolean \| void` | — | Hook to enrich or filter each event. Return `false` to drop it. |
```js
const tracker = createTracker('YOUR_CUSTOMER_KEY', 'YOUR_APP_NAME', {
errorTracking: {
suppressInDev: true,
maxEventsPerWindow: 10,
beforeCapture: (payload) => {
// Drop noisy errors, or attach extra context before dispatch.
if (payload.message.includes('Network request failed')) {
return false; // suppress this event
}
},
},
});
```
#### Capture Render-phase Errors with `ConvivaErrorBoundary`
Errors thrown during a component's render are not caught by the global handler. Wrap any part of your tree in `ConvivaErrorBoundary` to capture those errors and render a fallback UI(optional).
```jsx
import { ConvivaErrorBoundary } from '@convivainc/conviva-react-native-appanalytics';
<ConvivaErrorBoundary
name="CheckoutScreen"
fallback={({ error, reset }) => (
<View>
<Text>Something went wrong: {String(error && error.message)}</Text>
<Button title="Try again" onPress={reset} />
</View>
)}
>
<CheckoutScreen />
</ConvivaErrorBoundary>
```
| Prop | Type | Description |
|---|---|---|
| `children` | `ReactNode` | The subtree to protect. |
| `fallback` | `ReactNode` or `({ error, reset }) => ReactNode` | What to render after an error is caught. |
| `name` | `string` | Human-readable label attached to the captured error. |
| `resetKeys` | `unknown[]` | When any value changes, the boundary resets and re-renders `children`. |
| `onError` | `(error, componentStack) => void` | Optional callback invoked when an error is caught. Must not throw. |
#### Report Errors Manually with `trackError`
Use `trackError` inside a `try/catch` to report errors you handle yourself. `message` is required; all other fields are optional.
```js
import { trackError } from '@convivainc/conviva-react-native-appanalytics';
try {
await riskyOperation();
} catch (error) {
try {
await trackError({
message: error.message,
errorType: error.name,
stackTrace: error.stack,
isFatal: false,
isHandled: true,
attributes: { feature: 'checkout', step: 'payment' },
});
} catch (e) {
console.error(e);
}
}
```
`trackError` is also available on the tracker instance as `tracker.trackError({ ... })`.
#### Attach Custom Attributes to Every Error
Use the `errorTracker` singleton to attach attributes that should appear on all subsequently captured errors (for example, app build or environment). Attributes persist until removed.
```js
import { errorTracker } from '@convivainc/conviva-react-native-appanalytics';
try {
errorTracker.addAttribute('appBuild', '2026.6.1');
errorTracker.addAttribute('environment', 'production');
// Remove when no longer relevant:
errorTracker.removeAttribute('environment');
} catch (error) {
console.error(error);
}
```
`errorTracker` also exposes `setEnabled(boolean)` to toggle capture at runtime and `setRateLimitingEnabled(boolean)` to toggle rate limiting.
#### Symbolication
Minified, production stack traces are symbolicated automatically by Conviva's backend — no source-map upload step is required in your build.
Note: For apps that ship JS via OTA updates, supply a `bundleId` in the `errorTracking` config so the backend can match the running bundle to its source maps.
---
## Auto-collected Events
Conviva automatically collects a rich set of app performance metrics after completing the Quick Start.
| Event | Occurrence | Requirements |
|---|---|---|
| `network_request` | After receiving a network request response | Android: requires android-plugin; iOS: auto-collected |
| `screen_view` | When a screen is interacted with on first launch or relaunch | Native sensors + Conviva instrumentation plugin + navigation container wrapping |
| `application_error` | When an unhandled error occurs in the application, including uncaught JavaScript errors and unhandled promise rejections | Auto-collected from native sensors; JS errors captured by the [Error Tracking](#error-tracking) module |
| `button_click` | On button click callback | Native sensors + Conviva instrumentation babel plugin |
| `application_background` | When the app moves to the background | Auto-collected from native sensors |
| `application_foreground` | When the app moves to the foreground | Auto-collected from native sensors |
| `application_install` | When the app is launched for the first time after install | Auto-collected from native sensors |
### Validation
To verify the integration for auto-collected events, check the [validation dashboard](https://pulse.conviva.com/app/appmanager/ecoIntegration/validation) _(Conviva login required)_.
---
## FAQ
[DPI Integration FAQ](https://pulse.conviva.com/learning-center/content/sensor_developer_center/tools/eco_integration/eco_integration_faq.htm)