Skip to content

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:

OptionDefaultNotes
hostrequiredAZ-Five deployment base URL
project'default'Logical event stream within the org
batchSize10Queue length that triggers a flush
flushIntervalMs5000Periodic flush
maxQueueSize1000Drop-oldest on overflow
optOutfalseStart opted out (persisted opt-out wins)
gzipfalseGzip event POST bodies
disableDecidefalseSkip flags/surveys/recording bootstrap
sessionIdleTimeoutMs30 minSession 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-native and React Native platform properties ($os, $device_model, screen dimensions).
  • Failed batches — 429 included — 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.