@oursprivacy/react-native
v1.4.2
Published
Official React Native Tracking Library for OursPrivacy Analytics
Maintainers
Readme
Ours Privacy React Native SDK
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-storageInstall @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_groupop.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 defaultPropertiesNote:
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 / Profiles —
mixpanel.getPeople(),people.set(),people.increment(), etc. - Groups —
mixpanel.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
