React Native SDK
Capture events from React Native apps — a thin adapter over @azfive/capture with AsyncStorage persistence, lifecycle wiring and screen tracking.
@azfive/capture-react-native brings AZ-Five product analytics to React Native: events, identity, sessions, feature flags & experiments, and surveys. It’s a thin adapter over @azfive/capture — same wire protocol, same API — adding AsyncStorage persistence, AppState lifecycle wiring, platform properties, and a react-navigation screen tracker. Same behavioral spec as every other SDK.
Install
npm install @azfive/capture-react-native @react-native-async-storage/async-storage
Create a public ingest token with “Mobile app token” enabled (Settings → API Keys → Public Ingest Tokens) — native requests carry no browser Origin, and tokens without that flag fail closed.
Initialize
import { init, azfive } from '@azfive/capture-react-native';
// once at app startup (async: hydrates AsyncStorage)
await init('azfive_pub_…', { host: 'https://app.az-five.com', project: 'mobile' });
init is async because it hydrates AsyncStorage before capture starts — identity, super properties, and cached flags survive restarts. Without AsyncStorage installed, capture still works but identity won’t persist.
Lifecycle is automatic: events flush when the app backgrounds; sessions rotate after 30 minutes idle / 24 hours; flags refresh on foreground.
Capture events
azfive.capture('signed_up', { plan: 'pro' });
// Super properties — merged into every subsequent event
azfive.register({ deployment: 'eu-1' });
Screen tracking (az.screen_view) with react-navigation:
import { createScreenTracker } from '@azfive/capture-react-native';
const trackScreen = createScreenTracker(azfive);
<NavigationContainer
ref={navRef}
onStateChange={() => trackScreen(navRef.getCurrentRoute()?.name)}
>
Identify & person properties
azfive.identify('ava@example.com', { plan: 'pro' });
azfive.alias('legacy-77');
azfive.people.set({ favorite_color: 'teal' });
azfive.people.set_once({ signup_date: '2026-08-01' });
// on logout:
await azfive.flush();
azfive.reset(); // new anonymous id; reset(true) also rotates the device id
identify merges the anonymous session into the person (az.identify with $anonymous_id) and refetches flags. Opt-out controls — opt_in_capturing() / opt_out_capturing() / has_opted_out_capturing() — drop events at capture time, persist, and survive reset().
Feature flags
Flags load from /v1/decide on init, persist for stale-while-revalidate startup, and refetch on identify / reset and app foreground:
azfive.onFlags(() => {
const variant = azfive.getFlag('exp-checkout'); // 'control' | 'test' | false
if (azfive.isFlagEnabled('new-billing')) {
const payload = azfive.getFlagPayload('new-billing'); // no exposure event
}
});
await azfive.reloadFlags(); // force a refetch
getFlag and isFlagEnabled capture an az.flag_called exposure automatically, deduped per session:flag:value. getFlagPayload never does.
Surveys
Render decide-delivered surveys with the bundled Modal component:
import { SurveyController, AzFiveSurveys, azfive } from '@azfive/capture-react-native';
const controller = new SurveyController({ store, keyBase, capture: azfive.capture.bind(azfive) });
<AzFiveSurveys
client={azfive}
controller={controller}
getCurrentScreen={() => navRef.getCurrentRoute()?.name ?? ''}
screen={currentRouteName}
/>
Selection, suppression, and branching run through the shared engine in @azfive/capture; responses are captured as az.survey_shown / az.survey_dismissed / az.survey_sent events.
Flush & shutdown
Delivery is automatic (10 events / 5 s), and the queue flushes when the app backgrounds. flush() forces delivery and returns a promise; destroy() removes listeners and timers.
Reference
Config
The config is the @azfive/capture config minus the browser-only options (autocapture, captureClicks, persistence, storage, secretKey — the adapter manages persistence itself), with host required:
| Option | Default | Notes |
|---|---|---|
host | required | AZ-Five deployment base URL |
project | 'default' | Logical event stream within the org |
batchSize | 10 | Queue length that triggers a flush |
flushIntervalMs | 5000 | Periodic flush |
maxQueueSize | 1000 | Drop-oldest on overflow |
optOut | false | Start opted out (persisted opt-out wins) |
gzip | false | Gzip event POST bodies |
disableDecide | false | Skip flags/surveys/recording bootstrap |
sessionIdleTimeoutMs | 30 min | Session rotation on inactivity |
API
Identical to @azfive/capture: capture · identify · alias · reset · getDistinctId · getSessionId · register / register_once / unregister · people.set / people.set_once · opt_in_capturing / opt_out_capturing / has_opted_out_capturing · getFlag / isFlagEnabled / getFlagPayload / onFlags / reloadFlags · getSurveys · flush · destroy — plus createScreenTracker, SurveyController, and AzFiveSurveys.
Behavior notes
- Events are stamped with
$sdk: azfive-react-nativeand React Native platform properties ($os,$device_model, screen dimensions). - Failed batches —
429included — re-queue at the front and retry next flush; the public API never throws for delivery or flag problems. - Custom event names: anything except the reserved
az.prefix, ≤ 200 characters; properties ≤ 64 KiB serialized.