npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@oursprivacy/react-native

v1.4.2

Published

Official React Native Tracking Library for OursPrivacy Analytics

Readme

Ours Privacy React Native SDK

npm version GitHub

Privacy-first analytics for React Native.

This SDK is pure JavaScript. It does not ship native iOS or Android modules.


Table of Contents


Quick Start

1. Install

npm install @oursprivacy/react-native
npm install @react-native-async-storage/async-storage

Install @react-native-async-storage/async-storage directly in your app if you want persistent storage in bare React Native projects. Without it, the SDK falls back to in-memory storage.

2. Initialize

import { OursPrivacy } from '@oursprivacy/react-native';

const op = new OursPrivacy('YOUR_API_TOKEN', false);
await op.init();

That's it. The SDK connects to https://cdn.oursprivacy.com by default — no endpoint configuration needed.

3. Track Events

op.track('Button Pressed');
op.track('Purchase', { value: 49.99, currency: 'USD' });

4. Identify Users

After login, link events to a user:

await op.identify('user-123', {
  email: '[email protected]',
  first_name: 'Jane',
});

5. Flush

Events are batched and sent every 10 seconds by default. To send immediately:

op.flush();

Complete Example

import React from 'react';
import { Button, SafeAreaView } from 'react-native';
import { OursPrivacy } from '@oursprivacy/react-native';

let op;

async function getClient() {
  if (!op) {
    op = new OursPrivacy('YOUR_API_TOKEN', false);
    await op.init(false, {
      default_event_properties: { app_version: '2.0.0' },
    });
  }
  return op;
}

export default function App() {
  return (
    <SafeAreaView>
      <Button
        title="Track Event"
        onPress={async () => {
          const client = await getClient();
          client.track('Button Pressed', { screen: 'Home' });
        }}
      />
    </SafeAreaView>
  );
}

API Reference

Initialization

new OursPrivacy(token, trackAutomaticEvents, useNative?, storage?)

Creates an OursPrivacy instance. You must call .init() before tracking.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | token | string | Yes | Your project token | | trackAutomaticEvents | boolean | Yes | Whether to track automatic events | | useNative | boolean | No | Accepted but ignored | | storage | OursPrivacyAsyncStorage | No | Custom AsyncStorage adapter |

Returns: OursPrivacy instance (call .init() to complete setup)

const op = new OursPrivacy('YOUR_API_TOKEN', false);

op.init(optOutTrackingDefault?, options?)

Initializes the SDK. Must be called before tracking.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | optOutTrackingDefault | boolean | No | If true, tracking is opted out by default (default: false) | | options | OursPrivacyInitOptions | No | Additional initialization options (see below) |

OursPrivacyInitOptions shape:

| Field | Type | Description | |-------|------|-------------| | visitor_id | string | Pre-set the visitor ID; sets is_manually_set_id: true on all events | | default_event_properties | object | Properties merged into eventProperties on every track() call | | default_user_custom_properties | object | Properties merged into userProperties.custom_properties on every event | | default_user_consent_properties | object | Properties merged into userProperties.consent on every event | | serverURL | string | Override the base URL used for requests, for example a local QA capture server | | initialURL | string | Deep link URL to parse on init — extracts UTM params, click IDs, and ours_visitor_id (see Deep Link Attribution) |

Returns: Promise<void>

// Minimal init
await op.init();

// With options
await op.init(false, {
  visitor_id: 'pre-known-id',
  default_event_properties: { platform: 'mobile', app_version: '2.0.0' },
  default_user_custom_properties: { tier: 'pro' },
  default_user_consent_properties: { marketing: true },
});

Core Tracking

op.track(eventName, properties?)

Track an event with optional properties.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | eventName | string | Yes | Name of the event | | properties | object | No | Key/value pairs to attach to the event |

Returns: void

op.track('Page View', { page: '/home', referrer: 'google' });

op.identify(id, userProperties?)

Associate all future track() calls with the given user identity. Call this after a user logs in.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | id | string | Yes | The user's known identifier (e.g. email or external ID) | | userProperties | OursPrivacyUserProperties | No | User properties to attach |

OursPrivacyUserProperties shape:

| Field | Type | Description | |-------|------|-------------| | email | string | User's email address | | external_id | string | ID from your own system | | phone_number | string | User's phone number | | first_name | string | First name | | last_name | string | Last name | | custom_properties | object | Arbitrary custom user attributes | | consent | object | Consent flags (e.g. { marketing: true }) |

Returns: Promise<void>

await op.identify('user-123', {
  email: '[email protected]',
  external_id: 'db-user-456',
  first_name: 'Jane',
  custom_properties: { tier: 'pro' },
  consent: { marketing: true },
});

op.flush()

Push all queued events to the server immediately. Useful before app close or logout.

Returns: void

op.flush();

op.reset()

Clear the current user identity and all default properties. Generates a new random visitor ID. Call this when a user logs out.

Returns: void

op.reset();

Default Properties

Default properties are automatically merged into every event the SDK sends. They are the primary way to attach persistent, per-user or per-session context without repeating it on every track() call.

These methods can be called at init time via options, or at any point afterwards.


op.updateDefaultEventProperties(properties)

Merge properties into eventProperties on every future track() call. Properties are merged shallowly — later calls overwrite earlier ones for the same key.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | properties | object | Yes | Key/value pairs to merge into default event properties |

Returns: void

// At init time:
await op.init(false, {
  default_event_properties: { app_version: '2.0.0', environment: 'production' },
});

// Or post-init (e.g. after fetching user data):
op.updateDefaultEventProperties({ experiment_group: 'variant_b' });

// Every subsequent track() will include these automatically:
op.track('Button Pressed'); // eventProperties includes app_version, environment, experiment_group

op.updateDefaultUserCustomProperties(properties)

Merge properties into userProperties.custom_properties on every future event. Useful for attaching user attributes that should travel with every event.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | properties | object | Yes | Key/value pairs to merge into default user custom properties |

Returns: void

// At init time:
await op.init(false, {
  default_user_custom_properties: { tier: 'pro' },
});

// Or post-init (e.g. after subscription status loads):
op.updateDefaultUserCustomProperties({ tier: 'enterprise', seats: 50 });

op.updateDefaultUserConsentProperties(properties)

Merge properties into userProperties.consent on every future event. Use this to send the user's consent state alongside all analytics events.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | properties | object | Yes | Key/value pairs to merge into default user consent properties |

Returns: void

// At init time:
await op.init(false, {
  default_user_consent_properties: { marketing: false, analytics: true },
});

// Or when the user updates their preferences:
op.updateDefaultUserConsentProperties({ marketing: true });

Configuration

op.setServerURL(serverURL)

Override the base URL after initialization.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | serverURL | string | Yes | Base URL for API requests |

Returns: void


op.setLoggingEnabled(loggingEnabled)

Enable or disable debug logging. All logging is disabled by default.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | loggingEnabled | boolean | Yes | Whether to enable SDK logging |

Returns: void

op.setLoggingEnabled(true);

op.setFlushOnBackground(flushOnBackground)

This method has no effect in the current SDK.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | flushOnBackground | boolean | Yes | Ignored |

Returns: void

op.setFlushOnBackground(false);

op.setFlushBatchSize(flushBatchSize)

Set the maximum number of events sent in a single network request. Maximum value is 50; values above 50 are clamped to 50.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | flushBatchSize | number | Yes | Number of events per batch (max 50) |

Returns: void

op.setFlushBatchSize(25);

Identity

op.getVisitorId()

Returns the stable visitor UUID for this install. Synchronous. No prefix.

Returns: string | null

const visitorId = op.getVisitorId();
console.log(visitorId); // e.g. "550e8400-e29b-41d4-a716-446655440000"

op.setVisitorId(visitorId)

Update the visitor ID after initialization. Use this for web-to-app identity stitching when the visitor ID arrives outside of a deep link (e.g. via a native bridge or async lookup).

Sets is_manually_set_id: true on all subsequent events.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | visitorId | string | Yes | The Ours Privacy visitor ID to adopt |

Returns: Promise<void>

await op.setVisitorId('550e8400-e29b-41d4-a716-446655440000');

Deep Link Attribution

op.trackDeepLink(url)

Parse a deep link URL for marketing attribution data and fire a $deep_link_opened event. Extracts UTM parameters, ad network click IDs, and ours_visitor_id for cross-platform identity stitching.

Parsed attribution params are merged into defaultProperties, so they appear on all subsequent track() calls.

Await the returned promise before calling track() to ensure attribution and visitor identity are fully applied.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | url | string | Yes | The deep link or initial URL to parse |

Returns: Promise<void>

import { Linking } from 'react-native';

// On cold start — await to ensure attribution is applied before tracking
const initialURL = await Linking.getInitialURL();
if (initialURL) {
  await op.trackDeepLink(initialURL);
}

// On warm start (app in background)
Linking.addEventListener('url', async ({ url }) => {
  await op.trackDeepLink(url);
});

Alternatively, pass the URL at init time:

const initialURL = await Linking.getInitialURL();
await op.init(false, {
  initialURL: initialURL || undefined,
});

Supported parameters:

| Category | Parameters | |----------|-----------| | UTM | utm_source, utm_medium, utm_campaign, utm_content, utm_term | | Google | gclid, gad_source, dclid, gbraid, wbraid | | Meta | fbclid, fbc, fbp | | Microsoft | msclkid | | TikTok | ttclid | | Twitter/X | twclid | | LinkedIn | li_fat_id | | Reddit | rdt_cid | | Snapchat | sccid | | Pinterest | epik | | Quora | qclid | | AppLovin | aleid, alart, axwrt | | Other | clickid, clid, ndclid, irclickid, im_ref, sacid, basis_cid | | Identity | ours_visitor_id — cross-platform visitor stitching |

AppLovin example:

When a user clicks an AppLovin ad, the deep link will contain aleid (click ID) and alart (app user ID):

// Deep link: myapp://open?aleid=click_abc&alart=user_xyz&utm_source=applovin
await op.trackDeepLink('myapp://open?aleid=click_abc&alart=user_xyz&utm_source=applovin');

// All subsequent events will include aleid, alart, and utm_source in defaultProperties

Note: esi (Event Source Indicator) is configured in the AppLovin destination mapping in the Ours Privacy dashboard, not in the SDK. Set it to "app" for mobile events in your destination settings.


Privacy Controls

op.optOutTracking()

Stop all tracking immediately. Any queued events that have not been flushed will be discarded. Call flush() first if you want to preserve queued events.

Returns: void

// Flush first to preserve any pending events
op.flush();
op.optOutTracking();

op.optInTracking()

Resume tracking after a previous call to optOutTracking(). This also sends an $opt_in event to the server.

Returns: void

op.optInTracking();

op.hasOptedOutTracking()

Check whether the current user has opted out of tracking.

Returns: Promise<boolean>

const hasOptedOut = await op.hasOptedOutTracking();
if (hasOptedOut) {
  console.log('User has opted out');
}

Payload Structure

The SDK sends a JSON body to POST /ingest on the configured serverURL. Understanding this structure is useful if you are building a proxy, using the local QA capture server, or verifying your data in the Ours Privacy dashboard.

{
  "token": "your-project-token",
  "is_manually_set_id": false,
  "data": [
    {
      "event": "Purchase",
      "visitor_id": "550e8400-e29b-41d4-a716-446655440000",
      "distinct_id": "ecff9f0e-d4f8-4d9e-b2f8-8d9b2fcdf7b2",
      "eventProperties": {
        "price": 99
      },
      "userProperties": {
        "custom_properties": {
          "tier": "pro"
        },
        "consent": {
          "marketing": true
        }
      },
      "defaultProperties": {
        "device_type": "mobile",
        "os_name": "iOS",
        "os_version": "17.0",
        "device_vendor": "Apple",
        "device_model": "iPhone 16 Pro",
        "version": "1.2.0"
      }
    }
  ]
}

Key fields:

| Field | Description | |-------|-------------| | token | Your project token | | is_manually_set_id | true when visitor ID was set via init() options, setVisitorId(), or ours_visitor_id in a deep link | | data | Array of event objects in this batch | | event | Event name | | visitor_id | Stable visitor UUID for this install (no prefix) | | distinct_id | Per-event UUID generated for this event occurrence | | eventProperties | Properties from track() merged with default event properties | | userProperties.custom_properties | From identify() and updateDefaultUserCustomProperties() | | userProperties.consent | From identify() and updateDefaultUserConsentProperties() | | defaultProperties | Automatically collected device/SDK metadata |


Migration from Mixpanel

This SDK was originally forked from the Mixpanel React Native SDK. If you are migrating from Mixpanel or from an earlier version of this SDK, note the following:

Removed features

The following Mixpanel-specific features have been removed and are not planned:

  • People / Profilesmixpanel.getPeople(), people.set(), people.increment(), etc.
  • Groupsmixpanel.getGroup(), setGroup(), addGroup(), etc.

These APIs do not exist in @oursprivacy/react-native and will throw if called.

Renamed package

# Remove Mixpanel
npm uninstall @mixpanel/react-native

# Install Ours Privacy
npm install @oursprivacy/react-native
npm install @react-native-async-storage/async-storage
// Before
import { Mixpanel } from '@mixpanel/react-native';
const mp = await Mixpanel.init('TOKEN', false);

// After
import { OursPrivacy } from '@oursprivacy/react-native';
const op = new OursPrivacy('TOKEN', false);
await op.init();

Default properties

Replace registerSuperProperties with the Ours Privacy default properties API:

// Event properties sent with every track() call
op.updateDefaultEventProperties({ plan: 'pro', environment: 'production' });

// Per-user custom properties sent on every event
op.updateDefaultUserCustomProperties({ tier: 'enterprise' });

// Consent state sent on every event
op.updateDefaultUserConsentProperties({ marketing: true, analytics: true });

Visitor ID

Use getVisitorId() instead of getDistinctId() — it returns a clean UUID synchronously:

const id = op.getVisitorId();

FAQ

Do I need to request permission through AppTrackingTransparency?

No. Ours Privacy does not use IDFA, so no ATT permission is required.

Why aren't my events showing up?

Events are batched and sent every 10 seconds by default. Call flush() to send immediately. Enable debug logging with setLoggingEnabled(true) to see what's happening.

What platforms are supported?

  • React Native >= 0.60
  • iOS and Android apps using React Native
  • Expo and other JavaScript-mode environments

Support