npm package: @qubriux/react-native-analytics-client
Description: Analytics client library for react-native
Author: Ashwin Thomas
Latest version: 1.0.9

# @qubriux/react-native-analytics-client

Mobile analytics SDK for React Native applications. Provides event tracking, session management, Kinesis streaming, and automatic session pings.

---

## Features

- React Native provider with `useQubriuxClient()` hook
- Automatic session creation and session timeout handling
- Periodic session ping (configurable)
- Event streaming through AWS Kinesis
- Local event queue with retry logic and periodic flushing

---

## Installation

```bash
npm install @qubriux/react-native-analytics-client
```

or

```bash
yarn add @qubriux/react-native-analytics-client
```

---

## React Native Setup Requirements

This SDK relies on parts of the AWS SDK v3 and modern Web APIs that React Native does not include by default. To ensure compatibility, the following must be added to your React Native project.

### 1. Install Required Native Dependancies
`@qubriux/react-native-analytics-client` uses mmkv storage to handle the event queue and retry for failed events. Install the required native modules for this.
```bash
npm install react-native-mmkv react-native-nitro-modules
```

### 2. Install Required Polyfills
These polyfills are not bundled with the analytics SDK and must be installed manually
```bash
npm install react-native-get-random-values react-native-url-polyfill
```
### 3. Import Polyfills at the Top of Your Entry File
Add the following imports at the very top of your application entry file (`index.js`, `index.tsx`, or `App.tsx`):
```ts
import 'react-native-get-random-values';
import 'react-native-url-polyfill/auto';
```
`react-native-get-random-values` is required because AWS SDK v3 depends on `crypto.getRandomValues()` for UUID and hashing.
`react-native-url-polyfill/auto` is required because AWS SDK relies on WHATWG URL and URLSearchParams, which React Native does not provide.

Without these imports, Kinesis, Cognito, and network utilities will fail at runtime.

### 4. Add Babel Plugin for AWS SDK Compatibility

AWS SDK v3 uses class static blocks, which Metro cannot parse unless this Babel plugin is enabled. Install it as a development dependency:
```bash
npm install --save-dev @babel/plugin-transform-class-static-block
```

### 5. Register the Babel Plugin

Add the following to your `babel.config.js`:
```js
{
  "plugins": ["@babel/plugin-transform-class-static-block"]
}
```
This enables the required transform and ensures AWS SDK modules build correctly.

---

## Quick Start

Wrap your app with the provider:

```tsx
import { QubriuxAnalyticsProvider } from "@qubriux/react-native-analytics-client";

export default function App() {
  return (
    <QubriuxAnalyticsProvider
      config={{
        parentEvent: "APP_EVENT",
        apiKey: "YOUR_API_KEY",
        merchantId: "MERCHANT_123",
        streamName: "analytics-stream",
        region: "ap-south-1",
        identityPoolId: "xx-xxxx-x:xxxx",
        environment: "PRODUCTION" // "SANDBOX" | "QA" | "PRODUCTION"
      }}
    >
      <RootNavigator />
    </QubriuxAnalyticsProvider>
  );
}
```

---

## Using the Hook

```tsx
import useQubriuxClient from "@qubriux/react-native-analytics-client";

const analytics = useQubriuxClient();
```

You now have full access to the `AnalyticsClient` instance.

---

## Initialization

Initialize analytics once in your app entry (usually inside a root-level component):

```ts
analytics.initialize({
  prefix: "app",           // required (3 characters)
  deviceId: "abcd1234",
  deviceType: "Pixel 10",
  platform: "android",
  osVersion: "14",
  appVersion: "1.0.0",
  sessionTimeoutDelta: 15, // minutes (default)
  sessionPingTimer: 2,     // minutes (default) - how often to ping the server
  flushPingTimer: 10       // minutes (default) - how often to flush queued events
});
```

This creates a new session and triggers the initial backend session-create event.

---

## Logging Events

Event names are strongly typed:

```ts
analytics.log("screen_view", { screen_name: "Home" });
analytics.log("sign_in", { sign_in_method: "GOOGLE" });
```

### Events and params:

| **Event Name**             | **Description**                                               | **Unique Parameters**                                                                   |
| -------------------------- | ------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| **app_installed**          | Triggered when the app is opened for the first time.          | —                                                                                       |
| **app_opened**             | Triggered whenever the app is launched.                       | —                                                                                       |
| **session_start**          | Indicates a new analytics session has started.                | —                                                                                       |
| **screen_view**            | Triggered when a user navigates to a screen.                  | `screen_name`, `previous_screen_name`, `timestamp`, `screen_params` (object)            |
| **sign_in**                | Triggered upon successful sign-in.                            | `sign_in_method` → `GUEST`, `EMAIL`, `PHONE`, `GOOGLE`, `APPLE`                         |
| **sign_up**                | Triggered upon successful account creation.                   | `sign_up_method` → `GUEST`, `EMAIL`, `PHONE`, `GOOGLE`, `APPLE`                         |
| **sign_out**               | Triggered when the user signs out.                            | `sign_out_type` → `MANUAL`, `TOKEN_EXPIRED`, `ACCOUNT_DELETED`                          |
| **notification_clicked**   | Triggered when a user taps a notification.                    | `notification_id`, `notification_action` (`navigation`, `default`), `redirected_screen` |
| **notification_blocked**   | Triggered when the user blocks push notifications.            | —                                                                                       |
| **notification_unblocked** | Triggered when the user re-enables push notifications.        | —                                                                                       |
| **dynamic_link_opened**    | Triggered when the app is opened via a dynamic link.          | `dynamic_link_url`                                                                      |
| **app_updated**            | Triggered when the user updates the app.                      | `app_previous_version`, `app_current_version`                                           |
| **session_end**            | Triggered when a session ends. Handled internally.            | `session_duration`                                                                      |

---

## Updating User or Device Properties

These updates automatically apply to all subsequent events.

```ts
analytics.setUserId("user_123");

analytics.setLocation({
  latitude: "12.97",
  longitude: "77.59",
  city: "Bangalore",    // optional
  country: "India",     // optional
  locality: "Indiranagar" // optional
});

analytics.setDeviceId("newDevice123");
analytics.setDeviceType("Android");
analytics.setAppVersion("2.0.0");
analytics.setPlatform("android");
analytics.setOsVersion("14");
analytics.setNetworkType("WIFI");
```

---

## Session Management & Queued Events

The SDK can automatically ping the server to keep sessions alive and flush queued events periodically. You must start these loops and clean them up when appropriate (e.g., when the app unmounts, though usually, these run for the app's lifecycle).

```tsx
useEffect(() => {
  // Start the background ping and flush loops
  analytics.ping();
  analytics.flushEventQueue();

  return () => {
    // Cleanup on unmount
    analytics.clearPing();
    analytics.clearFlush();
  };
}, []);
```

- **Ping**: Triggered every `sessionPingTimer` minutes. Keeps the session active.
- **Flush**: Triggered every `flushPingTimer` minutes. Retries sending failed events from the local queue. Note that `log()` also attempts to flush the queue immediately.

### Session Timeout

Configured via `sessionTimeoutDelta` (in minutes) during initialization. If the timeout is exceeded, a new session will be automatically created.

---

## Full Initialization Config Reference

```ts
interface AnalyticsInitPropsType {
  sessionTimeoutDelta?: number; // minutes (default 15)
  sessionPingTimer?: number;    // minutes (default 2)
  flushPingTimer?: number;      // minutes (default 10)

  prefix: string;               // required (3 chars)
  deviceId: string;
  deviceType: string;

  platform: string;             // "android" | "ios"
  osVersion: string;
  appVersion: string;
}
```

---

## API Reference

| Method | Description |
|--------|-------------|
| `initialize(config)` | Creates a session and initializes internal state |
| `log(event, params?)` | Logs an analytics event and attempts to flush queue |
| `ping()` | Starts the recurring session ping loop |
| `clearPing()` | Stops the ping loop |
| `flushEventQueue()` | Starts the recurring event flush loop |
| `clearFlush()` | Stops the flush loop |
| `setUserId(id)` | Set logged-in user ID |
| `setLocation(location)` | Update GPS location |
| `setDeviceId(id)` | Update device ID |
| `setDeviceType(type)` | Update device type |
| `setPlatform(platform)` | Update platform |
| `setOsVersion(ver)` | Update OS version |
| `setAppVersion(ver)` | Update app version |
| `setNetworkType(type)` | Update network type |
| `updateEventPermissions(config)` | Enable/disable specific secondary events |

---

## Event Blocking

You can dynamically enable or disable specific secondary events at runtime.

Note: Core events (e.g., `app_opened`, `session_start`) cannot be disabled.

```ts
analytics.updateEventPermissions({
  screen_view: "DISABLED",
  sign_in: "ENABLED",
  sign_up: "ENABLED",
  sign_out: "ENABLED",
  screen_exit: "DISABLED"
});
```

When an event is disabled, calling `analytics.log("event_name")` will be working and the event will not be queued or sent.

---

## License

MIT © Qubriux Inc.