Skip to main content
The React Native SDK requires the New Architecture. Supported on: iOS SDK 1.0.70+ · Android SDK 1.0.42+ · React Native SDK 1.0.7+ (New Architecture only)
The React Native SDK requires the New Architecture. Versions 1.0.6 and earlier shipped no podspec and no Android Gradle module, so they could not be linked into an app at all — install 1.0.7 or later.

Requirements

Before integrating the AppDNA React Native SDK, ensure your project meets the following minimum requirements: Bare React Native: set newArchEnabled=true in android/gradle.properties, and run the iOS pod install with RCT_NEW_ARCH_ENABLED=1. Expo: the config plugin does both for you — it writes newArchEnabled=true into android/gradle.properties and into ios/Podfile.properties.json, which is where Expo’s Podfile reads it from to set RCT_NEW_ARCH_ENABLED.
The React Native SDK delegates rendering, storage, and network I/O to the native iOS and Android SDKs, so every paywall, onboarding flow, and in-app message looks and feels platform-native. Your project must meet the native platform requirements as well.

Installation

Install the AppDNA SDK package:
Or with npm:
Then install the iOS Pods with the New Architecture enabled:

Bare RN, iOS: register the screen slot when your Podfile uses use_frameworks!

Expo apps can skip this section — the config plugin writes this override into the AppDelegate on every prebuild. It applies to bare React Native only. Skip it too if your app links pods as static libraries — nothing to do there. But if your Podfile has use_frameworks! (which any app with Firebase in its pod graph ends up needing, and the AppDNA core SDK depends on Firebase), you must hand the screen-slot view to React yourself. React Native’s generated component registry wraps its whole third-party component map in #ifndef RCT_DYNAMIC_FRAMEWORKS, so with dynamic frameworks nothing registers AppdnaScreenSlotView. There is no error and no warning — <AppDNAScreenSlot> simply renders React’s placeholder, Unimplemented component: <AppdnaScreenSlotView>, and the slot never appears. Add the override below to AppDelegate.mm. RCTAppDelegate already exposes the hook:
Everything else — every method, every event, every delegate — works without this. Only the inline <AppDNAScreenSlot> component needs it.

Expo

The package ships a config plugin. Add it to app.json and run a prebuild:
The plugin does five things, none of which Expo’s defaults give you: Options — all optional:
Expo SDK 53+ has a Swift AppDelegate, and the plugin cannot write the ObjC override (4) into it. Rather than leave <AppDNAScreenSlot> silently broken, expo prebuild fails with a directed error. Resolve it either by linking statically — { "useFrameworks": "static" }, which makes the override unnecessary because React Native’s own registry is then compiled in — or, if you do not use <AppDNAScreenSlot>, by acknowledging it with { "screenSlot": "skip" }. Every other SDK feature works in both cases.
Expo Go cannot host a native module. Use a development build.
Autolinking wires the native iOS and Android modules automatically — no manual linking step is required.

Firebase Configuration

The AppDNA SDK uses Firebase Firestore for real-time configuration delivery (paywalls, experiments, feature flags, onboarding flows). You must add Firebase configuration files for each platform your app targets.

Step 1: Download Firebase Config Files

  1. Log into your AppDNA Console
  2. Go to Settings → SDK
  3. Click Download Firebase Config to download both:
    • GoogleService-Info-AppDNA.plist (for iOS)
    • google-services-appdna.json (for Android)

Step 2: Add iOS Configuration

  1. Open ios/<YourApp>.xcworkspace in Xcode
  2. Drag GoogleService-Info-AppDNA.plist into your app target’s folder in the project navigator
  3. Ensure “Copy items if needed” is checked
  4. Select your app target in the “Add to targets” section

Step 3: Add Android Configuration

Place the google-services-appdna.json file in the Android app module directory:
Ensure the Google Services plugin is applied in your android/app/build.gradle:
And the classpath is added to android/build.gradle:
Without the Firebase config files, the SDK cannot fetch remote configuration (paywalls, experiments, feature flags). Events will still be tracked, but remote features will not work.
If your app already uses Firebase for your own services (Realtime Database, Analytics, Crashlytics), AppDNA automatically initializes a separate named Firebase instance using GoogleService-Info-AppDNA.plist (iOS) and google-services-appdna.json (Android). Your existing Firebase setup is not affected. Just add the AppDNA config files alongside your own.

Architecture

The @appdna-ai/react-native-sdk package is a thin TypeScript facade over a TurboModule. Rendering, storage, and network I/O all happen in the native iOS and Android SDKs; the facade marshals method calls and receives native callbacks. Method calls resolve through TurboModuleRegistry, and native events arrive on the generated event emitters — not through NativeEventEmitter, which under the New Architecture would subscribe to a channel nothing writes to.

Callbacks that native waits for

Most callbacks are one-way notifications. Eight are vetoes: native pauses and waits for your answer before it proceeds. Each may return a value or a Promise of one, so a handler can ask your own backend. If it takes longer than the veto timeout (5 seconds by default, vetoTimeout in configure), native applies the default in the last column and moves on. onPromoCodeSubmit is the one hook whose default is to refuse — a timeout means the code was never validated.
You never interact with the bridge directly. The AppDNA class and its module accessors provide a high-level TypeScript API.

Native Dependencies

The React Native SDK inherits the dependencies of the underlying native SDKs. These are resolved automatically by CocoaPods (iOS) and Gradle (Android):
If your project already includes these dependencies, ensure your version constraints are compatible with the versions above. CocoaPods and Gradle will resolve conflicts automatically in most cases.
Lottie and Rive animation support is provided by the native SDKs. On iOS, add lottie-ios and rive-ios to your Podfile if you use those formats. On Android, the equivalent dependencies are bundled with the native AppDNA SDK.

Import

Import the SDK in any TypeScript / JavaScript file where you need to use it:
This entry point exposes the AppDNA static class, every module accessor, the canonical delegate interfaces (AppDNAPushDelegate, AppDNAPaywallDelegate, AppDNAOnboardingDelegate, etc.), and all DTOs (Entitlement, ProductInfo, TransactionInfo, PaywallContext, …).

Verify Installation

After adding the dependency, verify the SDK is correctly installed by printing the version:
You should see a version string. If the call throws instead, the error names the exact cause: Expo Go, a missing pod install, an unsupported runtime, or the New Architecture being switched off.

Troubleshooting

If you encounter issues during integration, call AppDNA.diagnose() after configuration to get a full health report:
This prints a diagnostic report to the platform console (Xcode debug area on iOS, Logcat on Android):
Any items marked with indicate a configuration issue. Common fixes: For more verbose output, set logLevel: 'debug' in AppDNAOptions during development to surface SDK activity.

Next Steps

Once the SDK is installed, proceed to the Quickstart guide to configure the SDK and start tracking events.