Integrate SDK

Learn how to initialize and start the iOS SDK.

Recommended

Get started with our SDK integration wizard

  • Before integrating, you must Install the SDK.
  • This document contains example implementations. Make sure to replace the following:
    • <YOUR_DEV_KEY>: The AppsFlyer dev key.
    • <APPLE_APP_ID>: The Apple App ID (without the id prefix).
    • Additional placeholders, where needed.

Initializing the iOS SDK

Step 1: Import dependencies
Import AppsFlyerLib:

// AppDelegate.h
#import <AppsFlyerLib/AppsFlyerLib.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@end
import UIKit
import AppsFlyerLib

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    // ...
}

Step 2: Initialize the SDK
In didFinishLaunchingWithOptions configure your Apple App ID and AppsFlyer dev key:

[[AppsFlyerLib shared] setAppsFlyerDevKey:@"<YOUR_DEV_KEY>"];
[[AppsFlyerLib shared] setAppleAppID:@"<APPLE_APP_ID>"];
AppsFlyerLib.shared().appsFlyerDevKey = "<YOUR_DEV_KEY>"
AppsFlyerLib.shared().appleAppID = "<APPLE_APP_ID>"

Starting the iOS SDK

In applicationDidBecomeActive, call start:

[[AppsFlyerLib shared] start];
func applicationDidBecomeActive(_ application: UIApplication) {
    AppsFlyerLib.shared().start()
    // ...
}

Add SceneDelegate support

Optional

Do the following only if you use SceneDelegates:

In didFinishLaunchingWithOptions, add a UIApplicationDidBecomeActiveNotification observer and set it to run start:

@implementation AppDelegate
    // SceneDelegate support - start AppsFlyer SDK
    - (void)sendLaunch:(UIApplication *)application {
    [[AppsFlyerLib shared] start];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // ...
    // SceneDelegate support
    [[NSNotificationCenter defaultCenter] addObserver:self
     selector:@selector(sendLaunch:)
     name:UIApplicationDidBecomeActiveNotification
     object:nil];
    // ...
    return YES;
}
// ...
@end
import UIKit
import AppsFlyerLib
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        ...
        // SceneDelegate support
        NotificationCenter.default.addObserver(self, selector: NSSelectorFromString("sendLaunch"), name: UIApplicationdidBecomeActiveNotification, object: nil)
        return true
    }
    // SceneDelegate support - start AppsFlyer SDK
    @objc func sendLaunch() {
        AppsFlyerLib.shared().start()
    }
// ...
}

Start with completion handler

Optional

To confirm that the SDK started successfully and notified the AppsFlyer servers, call start with a completion handler. You can then apply logic to handle the success or failure of the SDK launch.

[[AppsFlyerLib shared] startWithCompletionHandler:^(NSDictionary<NSString *,id> *dictionary, NSError *error) {
        if (error) {
            NSLog(@"%@", error);
            return;
        }
        if (dictionary) {
            NSLog(@"%@", dictionary);
            return;
        }
    }];
AppsFlyerLib.shared()?.start(completionHandler: { (dictionary, error) in
            if (error != nil){
                print(error ?? "")
                return
            } else {
                print(dictionary ?? "")
                return
            }
        })

Full example

#import "AppDelegate.h"
#import <AppsFlyerLib/AppsFlyerLib.h>
#import <UserNotifications/UserNotifications.h>
@interface AppDelegate ()
@end
@implementation AppDelegate
    // Start the AppsFlyer SDK
    - (void)sendLaunch:(UIApplication *)application {
    [[AppsFlyerLib shared] start];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    /** APPSFLYER INIT **/
    [AppsFlyerLib shared].appsFlyerDevKey = @"<YOUR_DEV_KEY>";
    [AppsFlyerLib shared].appleAppID = @"<APPLE_APP_ID>";
    /* Uncomment the following line to see AppsFlyer debug logs */
    // [AppsFlyerLib shared].isDebug = true;
  
    // SceneDelegate support
    [[NSNotificationCenter defaultCenter] addObserver:self
     selector:@selector(sendLaunch:)
     name:UIApplicationDidBecomeActiveNotification
     object:nil];
    if (@available(iOS 10, *)) {
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        center.delegate = self;
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error) {
        }];
    }

    else {
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes: UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
    }

    [[UIApplication sharedApplication] registerForRemoteNotifications];
    return YES;
}

@end
import UIKit
import AppsFlyerLib
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        AppsFlyerLib.shared().appsFlyerDevKey = "<YOUR_DEV_KEY>"
        AppsFlyerLib.shared().appleAppID = "<APPLE_APP_ID>"
        /* Uncomment the following line to see AppsFlyer debug logs */
        // AppsFlyerLib.shared().isDebug = true
        // SceneDelegate support
        NotificationCenter.default.addObserver(self, selector: NSSelectorFromString("sendLaunch"), name: UIApplication.didBecomeActiveNotification, object: nil)
        return true
    }
    // SceneDelegate support
    @objc func sendLaunch() {
        AppsFlyerLib.shared().start()
    }
// ...
}

Github link

See Setting the Customer User ID to associate a CUID with this integration.

Log sessions

The SDK sends an af_app_opened message whenever the app is opened or brought to the foreground, providing that start is called in the didBecomeActive lifecycle event method. Before the message is sent, the SDK makes sure that the time passed since sending the last message is not smaller than a predefined interval.

Setting the time interval between app launches

Set minTimeBetweenSessions to the minimal time interval that must lapse between two af_app_opened messages. The default interval is 5 seconds.

iOS 14 support

Following are guides on setting up support for iOS 14+ features.

Enabling App Tracking Transparency (ATT) support

Starting iOS 14.5, IDFA access is governed by the ATT framework.
Enabling ATT support in the SDK handles IDFA collection on devices with iOS 14.5+ installed.

🚧

Attention

Call waitForATTUserAuthorization only if you intend to call requestTrackingAuthorization somewhere in your app.

Step 1: Set up waitForATTUserAuthorization
When Initializing the SDK, before calling start In applicationDidBecomeActive, call waitForATTUserAuthorization:

[[AppsFlyerLib shared] waitForATTUserAuthorizationWithTimeoutInterval:60];
AppsFlyerLib.shared().waitForATTUserAuthorization(timeoutInterval: 60)

Github link

Set timeoutInterval as such that app users have enough time to see and engage with the ATT prompt. A few examples:

  • If ATT prompt is displayed on app launch–a 60-second interval should be enough
  • If ATT prompt is displayed after a tutorial that takes approximately 2 minutes to complete–a 120-second interval should be enough.

Step 2: Call requestTrackingAuthorization
Call requestTrackingAuthorization where you wish to display the prompt:

- (void)didBecomeActiveNotification {
    // start is usually called here:
    // [[AppsFlyerLib shared] start]; 
    if @available(iOS 14, *) {
      
      [ATTrackingManager requestTrackingAuthorizationWithCompletionHandler:^(ATTrackingManagerAuthorizationStatus status) {
        NSLog(@"Status: %lu", (unsigned long)status);
      }];
    }
}
@objc func didBecomeActiveNotification() {
    // start is usually called here:
    // AppsFlyerLib.shared().start()
    if #available(iOS 14, *) {
      ATTrackingManager.requestTrackingAuthorization { (status) in
        switch status {
        case .denied:
            print("AuthorizationSatus is denied")
        case .notDetermined:
            print("AuthorizationSatus is notDetermined")
        case .restricted:
            print("AuthorizationSatus is restricted")
        case .authorized:
            print("AuthorizationSatus is authorized")
        @unknown default:
            fatalError("Invalid authorization status")
        }
      }
    }
}

Github link

📘

Note

  • You need to import the AppTrackingTransparency framework to call requestTrackingAuthorization.
  • According to Apple documentation:
    • requestTrackingAuthorization is invoked only if the app is in the UIApplicationStateActive state.
    • requestTrackingAuthorization can't be invoked from App Extensions.

Customizing the ATT consent dialog

The ATT consent dialog can be customized by modifying your Xcode project's info.plist:

For detailed instructions, see Apple's documentation.

Attributing App Clips

Apple App Clips attribution was introduced in iOS SDK V6.0.8. See our App Clips integration guide for detailed instructions.

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.

  1. Add the NSAdvertisingAttributionReportEndpoint key to your app's info.plist.
  2. 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.

  1. In your app's Info.plist, add a new key.
  2. Type the key name AdAttributionKit and select AdAttributionKit - Postback Copy URL from the pop-up menu.
  3. 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

You can enable debug logs by setting isDebug to true:

[AppsFlyerLib shared].isDebug = true;
AppsFlyerLib.shared().isDebug = true
📘

Note

To see full debug logs, make sure to set isDebug before invoking other SDK methods.

See example.

🚧

Warning

To avoid leaking sensitive information, make sure debug logs are disabled before distributing the app.

Test the integration

Easily test with our SDK wizard

Note

If you prefer not to use our recommended wizard, you can find detailed manual testing instructions here.

For a full troubleshooting checklist, see Troubleshooting.

Creating an iOS debug app

Optional

You can utilize Xcode's compilation configuration capabilities to configure an easy-to-use debug app. It will enable you to switch between your debug and production apps by tapping into Xcode's active compilation conditions.

📘

Note

If you don't mind mixing production data with test traffic, you can skip this section. All tests can be performed for both production and debug apps.

This is achieved by configuring a User-Defined Setting in your project's Build Settings and exposing it via an info.plist property.

Step 1: Add a debug app to AppsFlyer
Add a new pending iOS app to AppsFlyer or ask a team member with dashboard access to add it. Choose any available app ID–You will need it in step 3. Make sure the ID is 9 digits and starts with four 1s, for example, 111167538.

Step 2: Add a User-Defined Setting

  1. In Xcode, in the file navigator view, select your project root and go to Build Settings.
  2. Click + in the toolbar and select Add User-Defined Setting. In this case, we name it AF_APP_ID.
  3. Expand the newly created User-Defined Setting:
    • Set the Debug Conditional Setting to your test app's app ID (mentioned in step 1)
    • Set the Release Conditional Setting to your production app's app ID.

Step 3: Expose app IDs via info.plist
Go to the project's info.plist and add a new property (called AFAppID in this case). Set its value to $(AF_APP_ID) (based on the User-Defined Setting name in step 2).

Step 4: Retrieve and set the app ID
To access and use app ID during SDK initialization, add the following code to didFinishLaunchingWithOptions in your AppDelegate:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // ...
    guard let appID : String = Bundle.main.object(forInfoDictionaryKey: "AFAppID") as? String else {
        fatalError("Cannot find app ID")
    }
    AppsFlyerLib.shared().appleAppID = appID
    // ...
    return true
}

Step 5: Run app using Debug build configuration
To change the active build configuration:

  1. go to Product > Scheme > Edit Scheme....
  2. Select Run and change the Build configuration to Debug or Release, as needed.

Now, when you use the Debug configuration to build your app, Xcode will use the debug app ID that you configured in step 2.


Did this page help you?