> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appdna.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Overview

> Platform comparison and feature matrix for iOS, Android, Flutter, and React Native

AppDNA provides native SDKs for every major mobile platform. All four SDKs share an identical API surface, the same offline-first architecture, and full feature parity. Choose the SDK that matches your stack and get started in minutes.

## Choose Your Platform

<CardGroup cols={2}>
  <Card title="iOS" icon="apple" href="/sdks/ios/installation">
    Native Swift SDK distributed via Swift Package Manager and CocoaPods. Requires iOS 16.0+ and Swift 5.9+.
  </Card>

  <Card title="Android" icon="android" href="/sdks/android/installation">
    Kotlin SDK distributed via Maven Central (Gradle). Requires Android API 24+ and Kotlin 1.9+.
  </Card>

  <Card title="Flutter" icon="flutter" href="/sdks/flutter/installation">
    Dart package distributed via pub.dev. Requires Flutter 3.10+ and Dart 3.0+.
  </Card>

  <Card title="React Native" icon="react" href="/sdks/react-native/installation">
    TypeScript package distributed via npm. Requires React Native 0.76.9+ with the New Architecture enabled (RN 0.77+/Kotlin 2.0 supported via a version-gated Compose config).
  </Card>
</CardGroup>

***

## Platform Comparison

### Requirements

|                     | iOS            | Android                | Flutter       | React Native                    |
| ------------------- | -------------- | ---------------------- | ------------- | ------------------------------- |
| **Package**         | `AppDNASDK`    | `ai.appdna.sdk`        | `appdna_sdk`  | `@appdna-ai/react-native-sdk`   |
| **Language**        | Swift 5.9+     | Kotlin 1.9+            | Dart 3.0+     | TypeScript                      |
| **Min Platform**    | iOS 16.0       | Android API 24         | Flutter 3.10+ | React Native 0.76.9+ (New Arch) |
| **Distribution**    | SPM, CocoaPods | Maven Central (Gradle) | pub.dev       | npm                             |
| **Current Version** | 1.0.71         | 1.0.43                 | 1.0.9         | 1.0.8                           |

<Info>
  The React Native SDK requires the New Architecture. All four SDKs are generally available.
</Info>

### Dependencies

|                    | iOS                   | Android                    | Flutter                     | React Native         |
| ------------------ | --------------------- | -------------------------- | --------------------------- | -------------------- |
| **HTTP**           | URLSession (built-in) | OkHttp3                    | Platform channels           | NativeModules bridge |
| **Billing**        | StoreKit 2 (built-in) | Google Play Billing 7.0    | Platform channels to native | NativeModules bridge |
| **Config Sync**    | FirebaseFirestore     | Firebase Firestore 25.1.1  | Platform channels to native | NativeEventEmitter   |
| **Secure Storage** | KeychainAccess        | EncryptedSharedPreferences | Platform-specific           | Platform-specific    |

<Info>
  Flutter and React Native SDKs bridge to the native iOS and Android implementations under the hood. You do not need to add native dependencies manually -- they are bundled with the SDK.
</Info>

***

## Core API

Every SDK exposes the same five core methods. The API is intentionally minimal -- initialize once, identify your user, track events, and the SDK handles the rest.

### `configure`

Initialize the SDK with your API key. Call this exactly once at app startup.

<Tabs>
  <Tab title="iOS">
    ```swift theme={null}
    import AppDNASDK

    AppDNA.configure(
        apiKey: "adn_live_xxx",
        environment: .production,
        options: AppDNAOptions(logLevel: .debug)
    )
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    import ai.appdna.sdk.AppDNA
    import ai.appdna.sdk.AppDNAOptions
    import ai.appdna.sdk.Environment

    AppDNA.configure(
        context = this,
        apiKey = "adn_live_xxx",
        environment = Environment.PRODUCTION,
        options = AppDNAOptions(logLevel = LogLevel.DEBUG)
    )
    ```
  </Tab>

  <Tab title="Flutter">
    ```dart theme={null}
    import 'package:appdna_sdk/appdna_sdk.dart';

    await AppDNA.configure(
      apiKey: "adn_live_xxx",
      env: AppDNAEnvironment.production,
      options: AppDNAOptions(logLevel: AppDNALogLevel.debug),
    );
    ```
  </Tab>

  <Tab title="React Native">
    ```typescript theme={null}
    import { AppDNA } from '@appdna-ai/react-native-sdk';

    await AppDNA.configure("adn_live_xxx", "production", {
      logLevel: "debug",
    });
    ```
  </Tab>
</Tabs>

### `identify`

Link a user identity with optional traits. Traits are merged with previously set values.

<Tabs>
  <Tab title="iOS">
    ```swift theme={null}
    AppDNA.identify(
        userId: "user-123",
        traits: ["plan": "premium", "signup_date": "2025-01-15"]
    )
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    AppDNA.identify(
        userId = "user-123",
        traits = mapOf("plan" to "premium", "signup_date" to "2025-01-15")
    )
    ```
  </Tab>

  <Tab title="Flutter">
    ```dart theme={null}
    await AppDNA.identify("user-123", traits: {
      "plan": "premium",
      "signup_date": "2025-01-15",
    });
    ```
  </Tab>

  <Tab title="React Native">
    ```typescript theme={null}
    await AppDNA.identify("user-123", {
      plan: "premium",
      signup_date: "2025-01-15",
    });
    ```
  </Tab>
</Tabs>

### `track`

Record a custom event with optional properties. Events are queued locally and flushed automatically.

<Tabs>
  <Tab title="iOS">
    ```swift theme={null}
    AppDNA.track(
        event: "workout_completed",
        properties: ["duration": 45, "type": "strength"]
    )
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    AppDNA.track(
        event = "workout_completed",
        properties = mapOf("duration" to 45, "type" to "strength")
    )
    ```
  </Tab>

  <Tab title="Flutter">
    ```dart theme={null}
    await AppDNA.track("workout_completed", properties: {
      "duration": 45,
      "type": "strength",
    });
    ```
  </Tab>

  <Tab title="React Native">
    ```typescript theme={null}
    await AppDNA.track("workout_completed", {
      duration: 45,
      type: "strength",
    });
    ```
  </Tab>
</Tabs>

### `reset`

Clear the user identity on sign-out. The anonymous ID is preserved so device-level analytics continue uninterrupted.

<Tabs>
  <Tab title="iOS">
    ```swift theme={null}
    AppDNA.reset()
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    AppDNA.reset()
    ```
  </Tab>

  <Tab title="Flutter">
    ```dart theme={null}
    await AppDNA.reset();
    ```
  </Tab>

  <Tab title="React Native">
    ```typescript theme={null}
    await AppDNA.reset();
    ```
  </Tab>
</Tabs>

### `flush`

Force-send all queued events immediately. Useful before the app enters the background.

<Tabs>
  <Tab title="iOS">
    ```swift theme={null}
    AppDNA.flush()
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    AppDNA.flush()
    ```
  </Tab>

  <Tab title="Flutter">
    ```dart theme={null}
    await AppDNA.flush();
    ```
  </Tab>

  <Tab title="React Native">
    ```typescript theme={null}
    await AppDNA.flush();
    ```
  </Tab>
</Tabs>

***

## Module Namespaces

Beyond the core API, the SDK organizes features into **10 module namespaces**. Each namespace is accessed as a property on the `AppDNA` singleton and operates independently while sharing the core event pipeline, identity state, and configuration layer.

| Namespace       | Purpose                                            | Example                                                                  |
| --------------- | -------------------------------------------------- | ------------------------------------------------------------------------ |
| `push`          | Push notification registration and handling        | `AppDNA.push.requestPermission()` (on iOS the namespace is `pushModule`) |
| `billing`       | Subscription status, product fetching, purchases   | `AppDNA.billing.getProducts(["premium_monthly"])`                        |
| `onboarding`    | Server-driven onboarding flow presentation         | `AppDNA.onboarding.present("welcome")`                                   |
| `paywall`       | Server-driven paywall rendering and events         | `AppDNA.paywall.present("premium")`                                      |
| `remoteConfig`  | Key-value remote configuration                     | `AppDNA.remoteConfig.get("key")`                                         |
| `features`      | Feature flags and entitlements                     | `AppDNA.features.isEnabled("dark_mode")`                                 |
| `experiments`   | A/B experiment assignment and exposure tracking    | `AppDNA.experiments.getVariant("test")`                                  |
| `surveys`       | In-app survey presentation and response collection | `AppDNA.surveys.present("nps")`                                          |
| `inAppMessages` | Triggered in-app messaging                         | `AppDNA.inAppMessages.suppressDisplay(false)`                            |
| `deepLinks`     | Deep link routing and deferred deep links          | `AppDNA.deepLinks.handleURL(url)`                                        |

Every namespace is available on all four SDKs. Flutter and React Native are thin wrappers over the same native iOS and Android renderers, so the module surface is the same one — not a re-implementation of it.

***

## Delegate and Callback Protocols

Each module that communicates events back to your application uses a delegate or callback pattern. The core delegate protocols shared across all platforms include:

| Protocol                     | Key Methods                                                         | Used By         |
| ---------------------------- | ------------------------------------------------------------------- | --------------- |
| `AppDNAOnboardingDelegate`   | Flow started, step changed, flow completed, flow dismissed          | `onboarding`    |
| `AppDNAPaywallDelegate`      | Presented, dismissed, purchase started/completed/failed, promo code | `paywall`       |
| `AppDNASurveyDelegate`       | Presented, completed (with responses), dismissed                    | `surveys`       |
| `AppDNAInAppMessageDelegate` | Shown, action taken, dismissed, shouldShowMessage gate              | `inAppMessages` |
| `AppDNADeepLinkDelegate`     | Deep link received (url + params)                                   | `deepLinks`     |
| `AppDNAPushDelegate`         | Token received, notification presented, notification opened         | `pushModule`    |

<Tabs>
  <Tab title="iOS">
    Implement Swift **protocols** with default empty methods. Conform to only what you need:

    ```swift theme={null}
    class MyHandler: AppDNAPaywallDelegate {
        func onPaywallPresented(paywallId: String) { }
        func onPaywallDismissed(paywallId: String) { }
    }

    AppDNA.paywall.setDelegate(MyHandler())
    ```
  </Tab>

  <Tab title="Android">
    Implement Kotlin **interfaces** with default methods. Override only what you need:

    ```kotlin theme={null}
    AppDNA.paywall.setDelegate(object : AppDNAPaywallDelegate {
        override fun onPaywallPresented(paywallId: String) { }
        override fun onPaywallDismissed(paywallId: String) { }
    })
    ```
  </Tab>

  <Tab title="Flutter">
    Extend Dart **abstract classes**:

    ```dart theme={null}
    class MyHandler extends AppDNAPaywallDelegate {
      @override
      void onPaywallPresented(String paywallId) { }
      @override
      void onPaywallDismissed(String paywallId) { }
    }

    AppDNA.paywall.setDelegate(MyHandler());
    ```
  </Tab>

  <Tab title="React Native">
    Implement the **delegate interface** and register it once:

    ```typescript theme={null}
    const delegate: AppDNAPaywallDelegate = {
      onPaywallPresented: (paywallId) => {},
      onPaywallDismissed: (paywallId) => {},
      onPaywallAction: (paywallId, action) => {},
      onPaywallPurchaseStarted: () => {},
      onPaywallPurchaseCompleted: () => {},
      onPaywallPurchaseFailed: () => {},
      onPaywallRestoreStarted: () => {},
      onPaywallRestoreCompleted: () => {},
      onPaywallRestoreFailed: () => {},
      onPostPurchaseDeepLink: () => {},
      onPostPurchaseNextStep: () => {},
    };

    AppDNA.paywall.setDelegate(delegate);
    ```
  </Tab>
</Tabs>

***

## Architecture

### Offline-First Design

All four SDKs share the same offline-first architecture. Your app never crashes or degrades because of a network issue.

**Configuration priority** -- the SDK resolves config using a three-tier fallback:

```
Remote (Firestore real-time sync)
    |
    v  unavailable?
Cached (last successful fetch, persisted on device)
    |
    v  unavailable?
Bundled (appdna-config.json embedded in the app binary)
```

**Event queue** -- events are persisted to disk, batched, and flushed automatically:

| Setting        | Default    | Description                                         |
| -------------- | ---------- | --------------------------------------------------- |
| Flush interval | 30 seconds | Time between automatic flushes                      |
| Batch size     | 20 events  | Events are flushed when the batch reaches this size |
| Config TTL     | 1 hour     | Time before cached config is considered stale       |

Events survive app restarts and device reboots. They are only removed from the queue after the server acknowledges receipt.

### Experiment Bucketing

All SDKs use the same deterministic hashing algorithm for experiment assignment:

```
bucket = hash(userId, experimentId) % 10000
```

This guarantees that the same user sees the same variant across all platforms, all sessions, and all app versions -- with no server round-trip required.

### Config Bundle for CI/CD

Generate a versioned JSON config bundle on the server and embed it in your app binary for zero-latency first launch:

<Tabs>
  <Tab title="iOS">
    Add `appdna-config.json` to your Xcode project as a bundle resource.
  </Tab>

  <Tab title="Android">
    Place `appdna-config.json` in the `assets/` directory.
  </Tab>

  <Tab title="Flutter">
    Add `appdna-config.json` to your `assets/` folder and declare it in `pubspec.yaml`.
  </Tab>

  <Tab title="React Native">
    Place `appdna-config.json` in your project root or assets directory.
  </Tab>
</Tabs>

***

## Feature Parity Matrix

All four SDKs have feature parity. Flutter and React Native wrap the native iOS and Android SDKs — the rendering, business logic, storage, and network I/O are the same code paths, reached through a thin facade.

| Feature                   | iOS | Android | Flutter | React Native |
| ------------------------- | :-: | :-----: | :-----: | :----------: |
| Event tracking            | Yes |   Yes   |   Yes   |      Yes     |
| User identification       | Yes |   Yes   |   Yes   |      Yes     |
| Offline event queue       | Yes |   Yes   |   Yes   |      Yes     |
| Remote config             | Yes |   Yes   |   Yes   |      Yes     |
| Feature flags             | Yes |   Yes   |   Yes   |      Yes     |
| A/B experiments           | Yes |   Yes   |   Yes   |      Yes     |
| Push notifications        | Yes |   Yes   |   Yes   |      Yes     |
| Billing / subscriptions   | Yes |   Yes   |   Yes   |      Yes     |
| Server-driven onboarding  | Yes |   Yes   |   Yes   |      Yes     |
| Server-driven paywalls    | Yes |   Yes   |   Yes   |      Yes     |
| In-app messages           | Yes |   Yes   |   Yes   |      Yes     |
| Surveys                   | Yes |   Yes   |   Yes   |      Yes     |
| Deep links                | Yes |   Yes   |   Yes   |      Yes     |
| Config bundle embedding   | Yes |   Yes   |   Yes   |      Yes     |
| Consent management        | Yes |   Yes   |   Yes   |      Yes     |
| Deterministic experiments | Yes |   Yes   |   Yes   |      Yes     |

***

## Configuration Options

All SDKs accept the same configuration options at initialization:

| Option            | Type   | Default     | Description                                                                                                                                                |
| ----------------- | ------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `flushInterval`   | number | `30`        | Seconds between automatic event flushes                                                                                                                    |
| `batchSize`       | number | `20`        | Events to batch before flushing                                                                                                                            |
| `configTTL`       | number | `3600`      | Seconds before cached config is stale                                                                                                                      |
| `logLevel`        | enum   | `warning`   | Console log verbosity: `none`, `error`, `warning`, `info`, `debug`                                                                                         |
| `billingProvider` | enum   | `storeKit2` | Billing integration: `storeKit2` (iOS), `revenueCat`, `adapty`, or `none` (the platform's native store — Google Play Billing on Android, StoreKit on iOS). |

<Note>
  Use `logLevel: debug` during development and `logLevel: warning` or `logLevel: none` for production builds.
</Note>

***

## Environments

| Environment    | API Base URL            | Key Prefix  |
| -------------- | ----------------------- | ----------- |
| **Production** | `https://api.appdna.ai` | `adn_live_` |
| **Sandbox**    | `https://api.appdna.ai` | `adn_test_` |

Events, experiments, and configuration are completely isolated between environments. The SDK auto-detects the environment from your API key prefix.

<Warning>
  Never ship an app to production with a sandbox API key. Sandbox data is periodically purged and is not included in production analytics.
</Warning>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="iOS Installation" icon="apple" href="/sdks/ios/installation">
    Add AppDNA to your Xcode project via SPM or CocoaPods.
  </Card>

  <Card title="Android Installation" icon="android" href="/sdks/android/installation">
    Add AppDNA to your Gradle build.
  </Card>

  <Card title="Flutter Installation" icon="flutter" href="/sdks/flutter/installation">
    Add the appdna\_sdk package from pub.dev.
  </Card>

  <Card title="React Native Installation" icon="react" href="/sdks/react-native/installation">
    Install @appdna-ai/react-native-sdk from npm.
  </Card>
</CardGroup>

For architecture deep dives, see the [Core Concepts](/concepts) page. For CI/CD integration with config bundles, see the [Config Bundle Guide](/guides/config-bundle-cicd).
