> ## 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.

# iOS Quickstart

> Configure, identify, and track in 5 minutes

<Info>
  **Supported on:** iOS SDK `1.0.61+`
</Info>

This guide walks you through configuring the AppDNA SDK, identifying users, and tracking your first event.

## 1. Configure the SDK

Initialize AppDNA as early as possible in your app lifecycle. For UIKit apps, place this in `application(_:didFinishLaunchingWithOptions:)`. For SwiftUI apps, use the `App` initializer.

### UIKit

```swift theme={null}
import FirebaseCore
import AppDNASDK

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        FirebaseApp.configure()

        AppDNA.registerBackgroundTasks()
        AppDNA.configure(
            apiKey: "adn_live_xxx",
            environment: .production,
            options: AppDNAOptions(logLevel: .debug)
        )
        return true
    }
}
```

### SwiftUI

```swift theme={null}
import SwiftUI
import FirebaseCore
import AppDNASDK

@main
struct MyApp: App {
    init() {
        FirebaseApp.configure()

        AppDNA.configure(
            apiKey: "adn_live_xxx",
            environment: .production,
            options: AppDNAOptions(logLevel: .debug)
        )
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
```

<Note>
  For background event uploads in SwiftUI apps, use `@UIApplicationDelegateAdaptor` and call `AppDNA.registerBackgroundTasks()` in `didFinishLaunchingWithOptions`.
</Note>

<Note>
  **If you don't have your own Firebase:** Keep `FirebaseApp.configure()` as shown above — it initializes AppDNA's Firebase instance.

  **If you already use Firebase** (Analytics, Crashlytics, Realtime Database): Remove the `FirebaseApp.configure()` call entirely and just call `AppDNA.configure(...)`. The SDK automatically picks up `GoogleService-Info-AppDNA.plist` and creates its own named Firebase instance. Your existing Firebase setup is not affected.
</Note>

<Warning>
  Call `AppDNA.configure(...)` exactly once before using any other SDK methods. Calling it multiple times will result in undefined behavior.
</Warning>

### Configuration Options

The `AppDNAOptions` struct lets you customize SDK behavior:

| Parameter         | Type              | Default      | Description                                      |
| ----------------- | ----------------- | ------------ | ------------------------------------------------ |
| `flushInterval`   | `TimeInterval`    | `30`         | Seconds between automatic event flushes          |
| `batchSize`       | `Int`             | `20`         | Number of events to batch before flushing        |
| `configTTL`       | `TimeInterval`    | `3600`       | Seconds before cached config is considered stale |
| `logLevel`        | `LogLevel`        | `.warning`   | Verbosity of SDK console logs                    |
| `billingProvider` | `BillingProvider` | `.storeKit2` | Billing integration to use                       |

### Environment

The `Environment` enum controls which backend environment the SDK targets:

| Value         | Description                      |
| ------------- | -------------------------------- |
| `.production` | Production API and configuration |
| `.sandbox`    | Sandbox API for testing          |

### Log Level

The `LogLevel` enum controls console log verbosity:

| Value      | Description                  |
| ---------- | ---------------------------- |
| `.none`    | No logging                   |
| `.error`   | Errors only                  |
| `.warning` | Errors and warnings          |
| `.info`    | Errors, warnings, and info   |
| `.debug`   | All messages including debug |

<Info>
  Use `.debug` during development to see all SDK activity. Switch to `.warning` or `.none` for production builds.
</Info>

### Billing Provider

The `BillingProvider` enum specifies which billing system to use:

| Value              | Description                          |
| ------------------ | ------------------------------------ |
| `.storeKit2`       | Native StoreKit 2 (default)          |
| `.revenueCat`      | RevenueCat integration               |
| `.adapty(apiKey:)` | Adapty integration with your API key |
| `.none`            | Disable billing module               |

## 2. Wait for Ready State

The SDK fetches remote configuration asynchronously. Use `onReady` to know when the SDK is fully initialized:

```swift theme={null}
AppDNA.onReady {
    print("SDK ready — remote config loaded")
}
```

## 3. Identify Users

Once a user signs in, call `identify` to associate events with their user ID:

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

<Note>
  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.
</Note>

## 4. Track Events

Track user actions with `track`:

```swift theme={null}
AppDNA.track(
    event: "workout_completed",
    properties: [
        "duration": 45,
        "type": "strength"
    ]
)
```

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:

```swift theme={null}
AppDNA.flush()
```

This is useful before the app enters the background or when you need to ensure events are sent immediately.

## 6. Set User Consent

Control whether the SDK collects and sends analytics data:

```swift theme={null}
AppDNA.setConsent(analytics: true)
```

<Warning>
  When `analytics` is set to `false`, events are silently dropped and not queued. No data is sent to AppDNA servers until consent is granted.
</Warning>

## 7. Remote Config and Feature Flags

Retrieve server-side configuration values:

```swift theme={null}
let welcomeMessage = AppDNA.getRemoteConfig(key: "welcome_message")
```

Check whether a feature flag is enabled:

```swift theme={null}
let darkModeEnabled = AppDNA.isFeatureEnabled(flag: "dark_mode")
```

## 8. Experiments

Get the variant assigned to a user for an experiment:

```swift theme={null}
let variant = AppDNA.getExperimentVariant(experimentId: "paywall_test")
```

Check if the user is in a specific variant:

```swift theme={null}
let isInVariantB = AppDNA.isInVariant(
    experimentId: "paywall_test",
    variantId: "b"
)
```

## 9. Session Data

Store cross-module session data that can be used in template interpolation across onboarding flows, paywalls, and in-app messages:

```swift theme={null}
// Store session data
AppDNA.setSessionData(key: "selected_plan", value: "premium")
AppDNA.setSessionData(key: "referral_code", value: "FRIEND2026")

// Retrieve session data
let plan = AppDNA.getSessionData(key: "selected_plan") // "premium"

// Clear all session data
AppDNA.clearSessionData()
```

Session data values are accessible in Console-configured content using template syntax: `{{session.selected_plan}}`.

## 10. Reset on Logout

When a user signs out, call `reset` to clear the user identity and flush any remaining events:

```swift theme={null}
AppDNA.reset()
```

This clears the identified user, generates a new anonymous ID, and flushes queued events.

<Check>
  You now have the SDK configured, user identification, event tracking, remote config, experiments, and session data working. Continue to the module-specific guides for [Push Notifications](/sdks/ios/push), [Billing](/sdks/ios/billing), [Onboarding](/sdks/ios/onboarding), and [Paywalls](/sdks/ios/paywall).
</Check>
