Skip to main content
Supported on: iOS SDK 1.0.70+ · Android SDK 1.0.42+ · React Native SDK 1.0.7+ (New Architecture only)
This guide walks you through configuring the AppDNA SDK, identifying users, and tracking your first event in a React Native application.

1. Configure the SDK

Initialize AppDNA as early as possible in your app lifecycle, typically in your app entry point (index.js, App.tsx, or similar) before rendering the root component:
If you don’t have your own Firebase: The AppDNA SDK manages a separate named Firebase instance internally — no firebase package install required.If you already use Firebase in your app (via @react-native-firebase/app or similar): the SDK automatically initializes its own named Firebase instance from GoogleService-Info-AppDNA.plist (iOS) and google-services-appdna.json (Android). Your existing Firebase setup is not affected.
Call AppDNA.configure(...) exactly once before using any other SDK methods. Calling it multiple times will result in undefined behavior.

Configuration Options

The AppDNAOptions interface lets you customize SDK behavior:

Environment

The AppDNAEnvironment type controls which backend environment the SDK targets:
There is no 'staging'. Which data you touch is decided by the API-key prefix (adn_test_ vs adn_live_); this value only tags the SDK’s own environment.

Log Level

The AppDNALogLevel type controls console log verbosity:
Use 'debug' during development to see all SDK activity. Switch to 'warning' or 'none' for production builds.

Billing Provider

The AppDNABillingProvider type specifies which billing system to use:
On Android the SDK uses Google Play Billing under the StoreKit2 alias. RevenueCat is supported across both platforms when the native bridges are configured.

2. Wait for Ready State

The SDK fetches remote configuration asynchronously. Use onReady to know when the SDK is fully initialized:
onReady() takes no callback — it returns a Promise that resolves once the remote configuration has been fetched and applied (immediately, if it already has).

3. Identify Users

Once a user signs in, call identify to associate events with their user ID:
Traits are merged with any previously set traits. You do not need to pass all traits on every call — only the ones that have changed.

4. Track Events

Track user actions with track:
track() is fire-and-forget: it returns void, not a Promise, so there is nothing to await. Native enqueues the event and batches the upload; call flush() when you need delivery. Events are batched and flushed automatically based on your flushInterval and batchSize settings.

5. Flush Events Manually

Force an immediate flush of all queued events:
This is useful before the app enters the background or when you need to ensure events are sent immediately. Control whether the SDK collects and sends analytics data:
setConsent takes a boolean — there is one analytics consent decision, not one per category. When consent is false, events are silently dropped and not queued. No data is sent to AppDNA servers until consent is granted. The decision is persistedsetConsent(false) survives a cold start.
Analytics are opt-OUT by default, and the default emits an event before the user has decided.requireConsent defaults to false. At that default, configure() emits sdk_initialized — carrying device, OS, locale and session context — before any consent decision exists. That is the SDK’s documented contract, not an accident: it is what every shipped version has done, and it matches Amplitude/Mixpanel/Firebase.If you need a lawful basis before the first byte leaves the device (EU/UK GDPR, and similar), you must ask for it:
With requireConsent: true, a user who has never been asked is treated as denied. Nothing else in the SDK will hold the events back for you.

7. Change Log Level at Runtime

Adjust the log level without reconfiguring the SDK:
Valid levels: 'none', 'error', 'warning', 'info', 'debug'.

8. Remote Config and Feature Flags

Retrieve server-side configuration values:
Check whether a feature flag is enabled:

9. Experiments

Get the variant assigned to a user for an experiment:
Check if the user is in a specific variant:
Inspect all experiment exposures collected during the current session:
Each exposure is a Record<string, unknown> carrying experimentId and variant.

10. Session Data

Store cross-module session data that can be used in template interpolation across onboarding flows, paywalls, and in-app messages:
Session data values are accessible in Console-configured content using template syntax: {{session.selected_plan}}. See the Rich Media guide for the full template namespace ({{user.*}}, {{session.*}}, {{device.*}}, {{remote_config.*}}).

11. Entitlements

Check whether the user has any active subscription (StoreKit, Play Billing, RevenueCat, or web entitlement):
Subscribe to live entitlement updates so your UI reflects renewals, cancellations, and restored purchases without polling:
See the Billing guide for the full purchase and restore flow.

12. Web Entitlement

Retrieve the current web entitlement (subscriptions granted outside the app store, e.g. via Stripe):
Listen for web entitlement changes in real time:
Check for a deferred deep link that brought the user to your app on first launch:

14. Get SDK Version

Print the underlying native SDK version (useful for support tickets):

15. Reset on Logout

When a user signs out, call reset to clear the user identity and flush any remaining events:
This clears the identified user, generates a new anonymous ID, and flushes queued events.

16. Shutdown

When the app is terminating, shut down the SDK to ensure all events are flushed and resources are released:
On both iOS and Android this flushes queued events and releases native resources. The wrapper also detaches every delegate, veto handler, and cached config snapshot, so a later configure() starts clean.
You now have the SDK configured with user identification, event tracking, remote config, experiments, entitlements, and deep links working. Continue to the module-specific guides for Push Notifications, Billing, Onboarding, and Paywalls.