Integrate iOS SDK 7
Initializing the iOS SDK
It's recommended to initialize the SDK in didFinishLaunchingWithOptions. This ensures the SDK can start in any scenario, including deep linking.
Step 1: Import dependencies
In your AppDelegate, import AppsFlyerLib:
// AppDelegate.h
#import <AppsFlyerLib/AppsFlyerLib.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@endimport UIKit
import AppsFlyerLib
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
// ...
}Step 2: Initialize the SDK
In didFinishLaunchingWithOptions, initialize the SDK with your dev key and Apple App ID:
[[AppsFlyerLib shared] initWithDevKey:@"<YOUR_DEV_KEY>" appleAppId:@"<APPLE_APP_ID>"];AppsFlyerLib.shared().initialize(devKey: "<YOUR_DEV_KEY>", appId: "<APPLE_APP_ID>")Configuring the SDK with AppsFlyerLibConfig.plist
Optional
SDK V7 introduces an optional property list file for configuring SDK behavior without code. Add AppsFlyerLibConfig.plist to your app's main bundle. The SDK loads it automatically during initialization, before initialize(devKey:appId:) is called. If the file is missing, the SDK uses defaults. If a key is absent from the plist, its default applies. Programmatic API calls always override plist values.
Supported keys
| Plist key | Type | Default | Programmatic equivalent |
|---|---|---|---|
debug_mode | Boolean | false | AppsFlyerLib.shared().isDebug = true |
currency_code | String | "USD" | AppsFlyerLib.shared().currencyCode = "ILS" |
disable_idfa_collection | Boolean | false | AppsFlyerLib.shared().disableAdvertisingIdentifier = true |
disable_idfv_collection | Boolean | false | AppsFlyerLib.shared().disableIDFVCollection = true |
disable_skadnetwork | Boolean | false | AppsFlyerLib.shared().disableSKAdNetwork = true |
min_time_between_sessions | Integer (seconds) | 30 | AppsFlyerLib.shared().minTimeBetweenSessions = 1 |
host | String | "" | AppsFlyerLib.shared().setHost("prefix", hostName: "host.com") |
prefix | String | "" | (set together with host) |
Example: AppsFlyerLibConfig.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>debug_mode</key>
<true/>
<key>currency_code</key>
<string>USD</string>
<key>disable_idfa_collection</key>
<false/>
<key>disable_idfv_collection</key>
<false/>
<key>disable_skadnetwork</key>
<false/>
<key>min_time_between_sessions</key>
<integer>30</integer>
<key>host</key>
<string></string>
<key>prefix</key>
<string></string>
</dict>
</plist>Adding the file to Xcode
- Choose File → New → File and select Property List.
- Name it exactly
AppsFlyerLibConfig(Xcode adds.plist). - Add it to your app target, not the test target.
- Verify it appears under Build Phases → Copy Bundle Resources.
NoteAny value set via the public API overwrites the corresponding plist value for the remainder of the process. On the next cold start, the plist value is loaded again.
Starting the iOS SDK
You control when the SDK sends its first session. Use registerSessionReadyListener to be notified when the SDK is ready, then call start when your app's conditions are met.
Without pre-conditions
Use this if your app has no pre-start conditions. If your app supports Universal Links, call handleLaunchOptions before registering the listener.
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[AppsFlyerLib shared] initWithDevKey:@"<YOUR_DEV_KEY>" appleAppId:@"<APPLE_APP_ID>"];
// Optional - only needed if supporting Universal Links
[[AppsFlyerLib shared] handleLaunchOptions:launchOptions];
[[AppsFlyerLib shared] registerSessionReadyListener:^{
// Collect ATT here if required before start
[[AppsFlyerLib shared] start];
}];
return YES;
}func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
AppsFlyerLib.shared().initialize(devKey: "<YOUR_DEV_KEY>", appId: "<APPLE_APP_ID>")
// Optional - only needed if supporting Universal Links
AppsFlyerLib.shared().handleLaunchOptions(launchOptions)
AppsFlyerLib.shared().registerSessionReadyListener {
// Collect ATT here if required before start
AppsFlyerLib.shared().start()
}
return true
}With pre-conditions
If start must wait for both SDK readiness and your consent flow (CMP, ATT, or a custom gate), use a lightweight coordinator. Each side sets a flag independently — the SDK when the listener fires, your app when the consent flow completes — and start is called only when both are set.
// AppDelegate.m
@interface AppDelegate ()
@property (nonatomic) BOOL consentGranted;
@property (nonatomic) BOOL sdkReady;
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[AppsFlyerLib shared] initWithDevKey:@"<YOUR_DEV_KEY>" appleAppId:@"<APPLE_APP_ID>"];
[[AppsFlyerLib shared] handleLaunchOptions:launchOptions];
__weak typeof(self) weakSelf = self;
[[AppsFlyerLib shared] registerSessionReadyListener:^{
weakSelf.sdkReady = YES;
[weakSelf startIfReady];
}];
// Trigger your CMP / ATT flow here.
// When it completes, set:
// self.consentGranted = YES;
// [self startIfReady];
return YES;
}
- (void)startIfReady {
if (self.consentGranted && self.sdkReady) {
[[AppsFlyerLib shared] start];
self.sdkReady = NO; // prevent duplicate starts in the same cycle
}
}
@endclass AppDelegate: UIResponder, UIApplicationDelegate {
private var consentGranted = false
private var sdkReady = false
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
AppsFlyerLib.shared().initialize(devKey: "<YOUR_DEV_KEY>", appId: "<APPLE_APP_ID>")
AppsFlyerLib.shared().handleLaunchOptions(launchOptions)
AppsFlyerLib.shared().registerSessionReadyListener { [weak self] in
self?.sdkReady = true
self?.startIfReady()
}
// Trigger your CMP / ATT flow here.
// When it completes, call:
// consentGranted = true
// startIfReady()
return true
}
private func startIfReady() {
guard consentGranted, sdkReady else { return }
AppsFlyerLib.shared().start()
sdkReady = false
}
}SwiftUI — use @UIApplicationDelegateAdaptor to wire the same AppDelegate:
@main
struct MyApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup { ContentView() }
}
}Unregistering
// Objective-C
[[AppsFlyerLib shared] unregisterSessionReadyListener];// Swift
AppsFlyerLib.shared().unregisterSessionReadyListener()Check session readiness
isSessionReady returns YES (true in Swift) when the session-ready listener has fired in the current foreground cycle. Use it to check readiness status from code paths that execute outside the listener callback — for example, deferred logic that runs after the initial startup sequence.
BOOL ready = [[AppsFlyerLib shared] isSessionReady];let ready = AppsFlyerLib.shared().isSessionReady()Full example
The following example demonstrates how to initialize and start the SDK without pre-conditions.
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[AppsFlyerLib shared] initWithDevKey:@"<YOUR_DEV_KEY>" appleAppId:@"<APPLE_APP_ID>"];
// Optional - only needed if supporting Universal Links
[[AppsFlyerLib shared] handleLaunchOptions:launchOptions];
[[AppsFlyerLib shared] registerSessionReadyListener:^{
// Collect ATT here if required before start
[[AppsFlyerLib shared] start];
}];
return YES;
}func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
AppsFlyerLib.shared().initialize(devKey: "<YOUR_DEV_KEY>", appId: "<APPLE_APP_ID>")
// Optional - only needed if supporting Universal Links
AppsFlyerLib.shared().handleLaunchOptions(launchOptions)
AppsFlyerLib.shared().registerSessionReadyListener {
// Collect ATT here if required before start
AppsFlyerLib.shared().start()
}
return true
}Setting the Customer User ID
Optional
The Customer User ID (CUID) is a unique user identifier created by the app owner outside the SDK. If made available to the SDK, it can be associated with installs and other in-app events. These CUID-tagged events can be cross-referenced with user data from other devices and applications.
Set the CUID
To set the CUID:
[AppsFlyerLib shared].customerUserID = @"my user id";AppsFlyerLib.shared().customerUserID = "my user id"
NoteThe Customer User ID must be set with every app launch.
Associate the CUID with the install event
If you need the CUID to be associated with the install event, set it before calling start. In SDK V7, since you control when start is called, set the CUID inside your registerSessionReadyListener callback before calling start.
Send SKAN and AdAttributionKit postback copies to AppsFlyer
If your app uses both SKAdNetwork and AdAttributionKit, configure both postback copy endpoints in the Info.plist file.
Send SKAN postback copies to AppsFlyer
Use this setup to send SKAdNetwork postback copies to AppsFlyer.
- Add the
NSAdvertisingAttributionReportEndpointkey to your app'sinfo.plist. - Set the key's value to
https://appsflyer-skadnetwork.com/.
Once configured, Apple will send SKAdNetwork postback copies to AppsFlyer. Copies of received postbacks are available in the postbacks copy report.
Send AdAttributionKit postback copies to AppsFlyer
Use this setup to send AdAttributionKit postback copies to AppsFlyer.
- In your app's Info.plist, add a new key.
- Type the key name
AdAttributionKitand selectAdAttributionKit - Postback Copy URLfrom the pop-up menu. - Set the key's value to
https://appsflyer-skadnetwork.com/.
Once configured, Apple will send AdAttributionKit postback copies to AppsFlyer. Copies of received postbacks are available in the postbacks copy report.
Enabling debug mode
Optional
You can enable debug logs by setting isDebug to true:
[AppsFlyerLib shared].isDebug = true;AppsFlyerLib.shared().isDebug = true
NoteTo see full debug logs, make sure to set
isDebugbefore invoking other SDK methods.
WarningTo avoid leaking sensitive information, make sure debug logs are disabled before distributing the app.
NoteAlternatively, you can enable debug mode at build time by setting
debug_modetotruein yourAppsFlyerLibConfig.plistfile. See Configuring the SDK with AppsFlyerLibConfig.plist above.
Testing the integration
For detailed integration testing instructions, see the iOS SDK integration testing guide.
Updated 3 days ago