# react-native-analytics-bridge

A navigator-agnostic analytics bridge for React Native. One unified API, multiple providers, with built-in session tracking, offline event queuing, GDPR privacy controls, and a flexible middleware pipeline.

## Why?

Most analytics solutions for React Native are thin wrappers around a single provider. Switching providers means rewriting your entire tracking implementation. This package separates your tracking calls from your provider — swap Segment for PostHog, or run both simultaneously, without touching your app code.

## Features

- **Multi-provider**: Segment, Mixpanel, Amplitude, Firebase, PostHog, RudderStack — or run multiple at once
- **Auto screen tracking**: Drop-in integrations for React Navigation and Expo Router
- **Session management**: Automatic session ID generation, session start/end events, background/foreground handling
- **Offline event queue**: Buffers events when offline, flushes on reconnect with exponential backoff retry
- **GDPR / Privacy**: Opt-out/opt-in support, PII field masking, consent management
- **Middleware pipeline**: Transform, filter, and enrich events before they reach any provider
- **TypeScript first**: Full type safety throughout
- **Custom adapters**: Implement your own provider in minutes

## Installation

```bash
npm install react-native-analytics-bridge
# or
yarn add react-native-analytics-bridge
```

Then install the peer dependency for whichever provider(s) you use — see the [Adapters](#adapters) section.

## Quick Start

```tsx
// analytics.ts
import {
  createAnalytics,
  createConsoleAdapter,
  createSegmentAdapter,
} from 'react-native-analytics-bridge';
import { createClient } from '@segment/analytics-react-native';

const segmentClient = createClient({ writeKey: 'YOUR_SEGMENT_KEY' });

export const analytics = createAnalytics({
  adapters: [
    createConsoleAdapter(),          // logs events in dev
    createSegmentAdapter({ client: segmentClient }),
  ],
  debug: __DEV__,
});

await analytics.initialize();
```

```tsx
// App.tsx
import { analytics } from './analytics';
import { useReactNavigationTracking } from 'react-native-analytics-bridge';

export default function App() {
  const { ref, onStateChange } = useReactNavigationTracking();

  return (
    <NavigationContainer ref={ref} onStateChange={onStateChange}>
      <Stack.Navigator>...</Stack.Navigator>
    </NavigationContainer>
  );
}
```

```tsx
// Any screen
import { useAnalytics } from 'react-native-analytics-bridge';

function CheckoutScreen() {
  const { track } = useAnalytics();

  const handlePurchase = () => {
    track('purchase_completed', {
      amount: 49.99,
      currency: 'USD',
      items: ['item_1', 'item_2'],
    });
  };

  return <Button onPress={handlePurchase} title="Buy Now" />;
}
```

## Core API

### `createAnalytics(config)`

Creates and returns the analytics manager. Call this once at app startup.

```ts
const analytics = createAnalytics({
  adapters: [...],          // required — at least one adapter
  privacy: {
    maskFields: ['email', 'phone'],
    defaultOptOut: false,
  },
  queue: {
    maxBatchSize: 20,       // flush after this many events
    flushInterval: 10000,   // flush every N ms
    maxRetries: 3,
  },
  session: {
    sessionTimeout: 1800000,          // 30 min inactivity = new session
    autoTrackSessionEvents: true,     // emit session_start / session_end
  },
  globalProperties: {
    app_version: '2.0.0',
    environment: 'production',
  },
  debug: __DEV__,
  onError: (error, event) => console.error('Analytics error', error),
});

await analytics.initialize();
```

### `getAnalytics()`

Returns the existing analytics instance from anywhere in your app.

```ts
import { getAnalytics } from 'react-native-analytics-bridge';

getAnalytics().track('button_pressed', { button: 'cta' });
```

### Tracking methods

```ts
// Track a custom event
analytics.track('video_played', { video_id: 'abc123', duration: 60 });

// Track a screen view
analytics.screen('ProductDetail', { product_id: 'xyz' });

// Identify a user
await analytics.identify('user_123', {
  name: 'Jane Doe',
  plan: 'pro',
});

// Associate user with a group/org
await analytics.group('org_456', { name: 'Acme Corp', plan: 'enterprise' });

// Alias two user identities (e.g. anonymous → logged in)
await analytics.alias('user_123');

// Reset on logout
await analytics.reset();

// Force flush the event queue
await analytics.flush();
```

## Screen Tracking

### React Navigation

```tsx
import { useReactNavigationTracking } from 'react-native-analytics-bridge';

function App() {
  const { ref, onStateChange } = useReactNavigationTracking({
    extraProperties: { platform: 'ios' },
  });

  return (
    <NavigationContainer ref={ref} onStateChange={onStateChange}>
      ...
    </NavigationContainer>
  );
}
```

### Expo Router

```tsx
// app/_layout.tsx
import { useExpoRouterTracking } from 'react-native-analytics-bridge';

export default function RootLayout() {
  useExpoRouterTracking();
  return <Stack />;
}
```

### Per-screen tracking hook

```tsx
import { useScreenTracking } from 'react-native-analytics-bridge';

function ProfileScreen({ userId }: { userId: string }) {
  useScreenTracking('Profile', { user_id: userId }, [userId]);
  return <View>...</View>;
}
```

## Hooks

### `useAnalytics()`

Access all analytics methods inside components.

```tsx
const { track, identify, reset, optOut, optIn } = useAnalytics();
```

### `useSession()`

Access current session info.

```tsx
const session = useSession();
console.log(session?.sessionId, session?.screenCount);
```

## Middleware

Middleware runs on every event before it reaches any adapter.

```ts
import {
  createPropertyEnricher,
  createEventFilter,
  createEventTransformer,
  createAttributionEnricher,
  createScreenFilter,
} from 'react-native-analytics-bridge';

// Add global properties to all events
analytics.addEventMiddleware(
  createPropertyEnricher({ app_version: '2.0.0', platform: 'ios' })
);

// Drop internal/debug events in production
analytics.addEventMiddleware(
  createEventFilter((event) => !event.name.startsWith('debug_'))
);

// Normalize event names to snake_case
analytics.addEventMiddleware(
  createEventTransformer((event) => ({
    ...event,
    name: event.name.toLowerCase().replace(/ /g, '_'),
  }))
);

// Add UTM attribution from a deep link
analytics.addEventMiddleware(
  createAttributionEnricher({ utm_source: 'email', utm_medium: 'newsletter' })
);

// Filter specific screens from tracking
analytics.addScreenMiddleware(
  createScreenFilter(['Loading', 'Splash', 'Transition'])
);
```

## Privacy & GDPR

```ts
const analytics = createAnalytics({
  adapters: [...],
  privacy: {
    maskFields: ['email', 'phone', 'credit_card'],  // masked to '***'
    maskValue: '[REDACTED]',                         // custom mask value
    defaultOptOut: false,                            // start opted in
  },
});

// User opts out — all tracking stops immediately
analytics.optOut();

// User opts back in
analytics.optIn();

// Check status
if (analytics.isOptedIn()) {
  analytics.track('settings_opened');
}
```

## Adapters

### Segment

```bash
npm install @segment/analytics-react-native
```

```ts
import { createClient } from '@segment/analytics-react-native';
import { createSegmentAdapter } from 'react-native-analytics-bridge';

const client = createClient({ writeKey: 'YOUR_KEY' });
createAnalytics({ adapters: [createSegmentAdapter({ client })] });
```

### Mixpanel

```bash
npm install mixpanel-react-native
```

```ts
import { Mixpanel } from 'mixpanel-react-native';
import { createMixpanelAdapter } from 'react-native-analytics-bridge';

const mixpanel = new Mixpanel('YOUR_TOKEN', true);
await mixpanel.init();
createAnalytics({ adapters: [createMixpanelAdapter({ instance: mixpanel })] });
```

### Amplitude

```bash
npm install @amplitude/analytics-react-native
```

```ts
import * as amplitude from '@amplitude/analytics-react-native';
import { createAmplitudeAdapter } from 'react-native-analytics-bridge';

await amplitude.init('YOUR_API_KEY').promise;
createAnalytics({ adapters: [createAmplitudeAdapter({ instance: amplitude })] });
```

### Firebase

```bash
npm install @react-native-firebase/app @react-native-firebase/analytics
```

```ts
import analytics from '@react-native-firebase/analytics';
import { createFirebaseAdapter } from 'react-native-analytics-bridge';

createAnalytics({ adapters: [createFirebaseAdapter({ instance: analytics() })] });
```

### PostHog

```bash
npm install posthog-react-native
```

```ts
import PostHog from 'posthog-react-native';
import { createPostHogAdapter } from 'react-native-analytics-bridge';

const posthog = await PostHog.initAsync('YOUR_API_KEY');
createAnalytics({ adapters: [createPostHogAdapter({ client: posthog })] });
```

### RudderStack

```bash
npm install @rudderstack/rudder-sdk-react-native
```

```ts
import rudderClient from '@rudderstack/rudder-sdk-react-native';
import { createRudderStackAdapter } from 'react-native-analytics-bridge';

await rudderClient.setup('YOUR_WRITE_KEY', { dataPlaneUrl: 'YOUR_URL' });
createAnalytics({ adapters: [createRudderStackAdapter({ client: rudderClient })] });
```

### Console (Debug)

Logs all events to the console — great for development.

```ts
import { createConsoleAdapter } from 'react-native-analytics-bridge';

createAnalytics({
  adapters: [
    createConsoleAdapter({ verbose: true }), // verbose: full JSON output
  ],
});
```

### Custom Adapter

Implement the `AnalyticsAdapter` interface to add any provider:

```ts
import type { AnalyticsAdapter } from 'react-native-analytics-bridge';

const myAdapter: AnalyticsAdapter = {
  name: 'my-provider',

  async initialize() {
    await MySDK.init('API_KEY');
  },

  async track(event) {
    await MySDK.logEvent(event.name, event.properties);
  },

  async screen(event) {
    await MySDK.logScreen(event.name);
  },

  async identify(payload) {
    await MySDK.setUser(payload.userId, payload.traits);
  },

  async reset() {
    await MySDK.logout();
  },
};
```

## TypeScript

Full types are exported:

```ts
import type {
  AnalyticsConfig,
  AnalyticsAdapter,
  AnalyticsEvent,
  ScreenEvent,
  UserTraits,
  SessionInfo,
  EventMiddlewareFn,
  ScreenMiddlewareFn,
  PrivacyConfig,
  QueueConfig,
  SessionConfig,
} from 'react-native-analytics-bridge';
```

## License

MIT

## Author

Oluwaseyi Roy (https://github.com/oluseyi-ged)
