Skip to main content
@traffical/react-native is the SDK for iOS and Android apps built with React Native. It handles the constraints mobile imposes — cold starts, offline use, app suspension, device context — and ships with sensible defaults so most apps don’t have to think about them.

Why mobile is different

Mobile has constraints web and backend don’t:
  • Cold start. On first launch there’s no cached bundle and no network response yet. The user sees the app before any experiment can resolve.
  • Offline use. Users open the app on planes and in subways. Resolution must work without connectivity.
  • App store latency. Code changes take days. Parameter changes via Traffical are instant — this is the whole point of having a remote configuration system at all.
  • Background suspension. The app may be paused for hours and resumed. Cached assignments need refreshing.
The React Native SDK defaults to evaluationMode: "server": each resolution is evaluated for that call’s context on the edge, and the response is cached and persisted to AsyncStorage across launches. Because getParams/decide are synchronous, a call returns the last-good cached response and converges as fresh resolves land. You can override with evaluationMode: "bundle" if you’d rather embed and evaluate the full bundle locally.

Installation

For iOS, run pod install in the ios/ directory after adding @react-native-async-storage/async-storage.

Setup

Use an SDK key (traffical_sk_..., scopes sdk:read+sdk:write) — browser-safe. The SDK auto-registers the AsyncStorage cache and lifecycle hooks for foreground/background transitions.

Resolving parameters

Same hook as the React SDK:

Cold start strategy

Resolution checks three sources in order: First launch, no localConfig: the user sees defaults until the first network call returns. If your first-launch onboarding is a critical experiment, embed a localConfig bundle built during CI:
Returning user: the SDK reads cached assignments from AsyncStorage synchronously before the first render. The user immediately sees their previous-session assignment. A background refresh updates for next time. Returning user after long absence (cache expired): falls back to localConfig, then to caller defaults.

Device-info enrichment

The SDK can enrich context with device info — useful for OS-specific experiments and analytics. You supply the data through a deviceInfoProvider: any object implementing the DeviceInfoProvider interface. The SDK ships the interface (DeviceInfoProvider / DeviceInfo types) but does not ship a built-in implementation, so you provide one — typically backed by react-native-device-info plus React Native’s Platform and Dimensions:
The returned fields merge into context on every resolution, so they’re available for policy conditions — e.g. osName eq "ios" for an iOS-only experiment.
Version-string targeting is a known gap. The numeric comparison operators (gt/gte/lt/lte) only compare numbers — a condition like appVersion gte "2.0.0" won’t match, because "2.0.0" is a string. To gate on a minimum version today, target an exact set of versions with in, or expose a numeric build number (appBuildNumber) and compare that. Semver-aware version conditions are not yet supported.

Tracking events

Events are batched in memory and flushed on background or app close.

Foreground refresh

When the app returns to the foreground after being suspended, the SDK checks whether the cache is stale and refreshes silently if so. Existing assignments stay stable — the refresh only matters for new parameters or next-session resolutions.

Options

Persistence is backed by AsyncStorage automatically — the provider registers it for you, so there’s no storage option to set. The provider also accepts the common options shared with the other SDKs (trackDecisions, exposureSessionTtlMs, eventBatchSize, eventFlushIntervalMs, disableCloudEvents, assignmentLogger, unitKeyFn, contextFn, plugins).

Next steps

Mobile experiment pattern

Onboarding and in-app experiments.

How it works

Evaluation modes and resolution.