Filters

iOS Basic Integration

Steps for basic integration of the Branch iOS SDK into your mobile app.

This page outlines the steps required to integrate the Branch iOS SDK. At the end, you will be ready to send Branch Events and use Branch Deep Links.

GitHubSDK SizeSpeedMin. Xcode VersionMin. OS Version
Repo~220kb for all featuresMedian 80ms to 250ms12.3+iOS 9+

Note: If you need to delay Branch initialization so you can request tacking permission from the user first or you need to set special initialization metadata because your third party data integration partner requires it, see Branch's iOS Advanced Features guide for relevant steps.

1. Configure Branch Dashboard

Start by configuring the Branch Dashboard for your application.

  1. Configure the default link settings for your app within the Configuration page of the Branch Dashboard.
  2. On the same page, confirm the "I have an iOS App" option is selected.
  1. Retrieve your Team ID from your Apple Developer Account.
  1. Go back to the Configuration page and use your Team ID as the value for your Apple App Prefix in the Branch Dashboard.

2. Configure Bundle Identifier

Next, make sure the Apple Bundle ID for your project matches the one in the Branch Dashboard.

  1. Find the bundle identifier for the relevant target associated with your project in Xcode, under the "Signing & Capabilities" tab.
  1. Return to the Configuration page of the Branch Dashboard, and use the "Add New Bundle ID" button to add your Bundle ID.

3. Configure Associated Domains

You will also need to tell your project what link domains it can expect Branch to use.

  1. In your Branch Dashboard, navigate to the "Link Domain" section of the Configuration page.
  1. Return to the "Signing & Capabilities" tab in Xcode, and add the domains from your Branch Dashboard to your project's target.
    • Use applinks:subdomain.app.link for the format.
    • The -alternate flag is required to ensure proper functioning of Universal Links and Deepviews for users that do not have your app installed.
    • The .test flag is required if you need to use a test key.

Please note: if you use a custom link domain, you will need to include your old link domain, your -alternate link domain, and your new link domain in your project.

4. Configure Info.plist

Branch requires certain key/value pairs to exist in your project's info.plist file. These include:

  • The branch_universal_link_domains key, which refers to your associated domains.
  • The branch_key key, where you add your live key and can choose to add your test key as well.
  • The URL types key, where you add values for your URL Schemes and URL Identifier.
    • Note: The Branch iOS SDK will pull the first URL Scheme from your list that is not one of fb, db, or pin. This value will be used one time to set the iOS URL Scheme under your Link Settings in the Branch Dashboard.

There are several ways you can update your info.plist file:

  1. As of Xcode 13, many project templates do not include an info.plist automatically. Instead, you can edit the "Custom iOS Target Properties" and "URL Types" sections of the "Info" tab for your target. When you add new, non-default fields to these sections, Xcode will generate an info.plist file for your project.
  1. If you already have an info.plist file, you can edit it in the Xcode UI by selecting it from the navigation.
  1. You also have the option to edit the XML in the info.plist file directly.
<plist version="1.0">
	<dict>
		<key>branch_universal_link_domains</key>
		<array>
			<string>n6lvk.app.link</string>
			<string>n6lvk-alternate.app.link</string>
			<string>n6lvk.test.app.link</string>
		</array>
		<key>CFBundleURLTypes</key>
		<array>
			<dict>
				<key>CFBundleTypeRole</key>
				<string>Editor</string>
				<key>CFBundleURLSchemes</key>
				<array>
					<string>branchsters</string>
				</array>
				<key>CFBundleURLName</key>
				<string>io.Branch.Branchsters</string>
			</dict>
		</array>
		<key>branch_key</key>
		<dict>
			<key>live</key>
			<string>key_live_aaa000AAA</string>
			<key>test</key>
			<string>key_test_bbb000BBB</string>
		</dict>
	</dict>
</plist>

5. Install Branch

Please choose one of the following integration methods to install the Branch SDK into your app.


Learn more about Swift Package Manager.

To add the Branch iOS SDK to your project as a Swift package dependency:

  1. In Xcode, go to File -> Add Packages.
  2. Use the search bar to look for either ios-branch-sdk-spm or https://github.com/BranchMetrics/ios-branch-sdk-spm.
  3. Select the ios-branch-sdk-spm package and click Add Package to continue through the installer.
  4. Check that the Branch iOS SDK now appears in your project's Package Dependencies tab.
  5. Navigate to your project's Build Phases tab and expand the Link Binary With Libraries section.
  6. Click on the + button to search for and add the following dependencies, noting the correct import status for each:
  7. Linked Frameworks and Libraries Import Status Description
    CoreServices Required Access and manage key operating system services, such as launch and identity services.
    SystemConfiguration Required Allow applications to access a device’s network configuration settings. Determine the reachability of the device, such as whether Wi-Fi or cell connectivity is active. Used for connection type.
    CoreTelephony Required Access information about a user’s cellular service provider, such as its unique identifier and whether the carrier allows VoIP. Used for mobile carrier.
    WebKit Required Integrate web content seamlessly into your app, and customize content interactions to meet your app’s needs. Used for web browser user agent.
    CoreSpotlight Required Index your app so users can search the content from Spotlight and Safari.
    AdServices Optional Attribute app-download campaigns that originate from the App Store, Apple News, or Stocks on iOS devices. This is used for obtaining Apple Attribution Token.
    AdSupport Optional Provide apps with access to an advertising identifier. This will give access to IDFA.
    StoreKit Optional Provide apps with ability to measure ad-driven installs via SKAdNetwork.
    LinkPresentation Optional Support customization of share sheet.
  8. Confirm that you have the required dependencies added, as well as any optional ones you would like, and that you have marked the "Status" column in Xcode appropriately.

Learn more about CocoaPods.

Note: CocoaPods does not support having multiple iOS Privacy Manifest files if you are not also using use_frameworks. If you are not using use_frameworks and have multiple Privacy Manifest files, you will need to condense them into one file. Make sure to include everything declared in the Branch iOS SDK's Privacy Manifest file.

To add the Branch iOS SDK to your project using the CocoaPods dependency manager:

  1. Open your project's podfile. If it doesn't have one yet, create one using pod init.
  2. Use the following sample code for your podfile, and base it on your project's requirements:
        		platform :ios, '12.0'
    
    # Replace APP_NAME with the name of your app
    target 'APP_NAME' do
    
    # If using Swift, include the following line:
    use_frameworks!
    
    	# For Branch iOS SDK 2.0.0+
    	pod 'BranchSDK'
    
    	# For Branch iOS SDK <2.0.0, remove previous pod line and uncomment the following line:
    	# pod 'Branch'
    end
        	
  3. Run pod install && pod update to install the project dependencies.
  4. Confirm in your target's General tab that a Pods_... dependency is now listed.

Learn more about Carthage.

Please note that Carthage 0.37.0+ is required for xcframework support, and in turn Branch requires the Carthage --use-xcframeworks option.

To add the Branch iOS SDK to your project using the Carthage dependency manager:

  1. Add github "BranchMetrics/ios-branch-deep-linking" to your project's Cartfile.
  2. Navigate to your project's Build Phases tab and expand the Link Binary With Libraries section.
  3. Click on the + button to search for and add the following dependencies, noting the correct import status for each:
  4. Linked Frameworks and Libraries Import Status Description
    CoreServices Required Access and manage key operating system services, such as launch and identity services.
    SystemConfiguration Required Allow applications to access a device’s network configuration settings. Determine the reachability of the device, such as whether Wi-Fi or cell connectivity is active. Used for connection type.
    CoreTelephony Required Access information about a user’s cellular service provider, such as its unique identifier and whether the carrier allows VoIP. Used for mobile carrier.
    WebKit Required Integrate web content seamlessly into your app, and customize content interactions to meet your app’s needs. Used for web browser user agent.
    CoreSpotlight Required Index your app so users can search the content from Spotlight and Safari.
    AdServices Optional Attribute app-download campaigns that originate from the App Store, Apple News, or Stocks on iOS devices. This is used for obtaining Apple Attribution Token.
    AdSupport Optional Provide apps with access to an advertising identifier. This will give access to IDFA.
    StoreKit Optional Provide apps with ability to measure ad-driven installs via SKAdNetwork.
    LinkPresentation Optional Support customization of share sheet.
  5. Confirm that you have the required dependencies added, as well as any optional ones you would like, and that you have marked the "Status" column in Xcode appropriately.

  1. Manually install the Branch xcframework from GitHub. If you prefer a static xcframework, please download the pre-built Branch static ZIP file available with Branch iOS SDK v1.38.0+.
  2. Navigate to your project's Build Phases tab and expand the Link Binary With Libraries section.
  3. Click on the + button to search for and add the following dependencies, noting the correct import status for each:
  4. Linked Frameworks and Libraries Import Status Description
    CoreServices Required Access and manage key operating system services, such as launch and identity services.
    SystemConfiguration Required Allow applications to access a device’s network configuration settings. Determine the reachability of the device, such as whether Wi-Fi or cell connectivity is active. Used for connection type.
    CoreTelephony Required Access information about a user’s cellular service provider, such as its unique identifier and whether the carrier allows VoIP. Used for mobile carrier.
    WebKit Required Integrate web content seamlessly into your app, and customize content interactions to meet your app’s needs. Used for web browser user agent.
    CoreSpotlight Required Index your app so users can search the content from Spotlight and Safari.
    AdServices Optional Attribute app-download campaigns that originate from the App Store, Apple News, or Stocks on iOS devices. This is used for obtaining Apple Attribution Token.
    AdSupport Optional Provide apps with access to an advertising identifier. This will give access to IDFA.
    StoreKit Optional Provide apps with ability to measure ad-driven installs via SKAdNetwork.
    LinkPresentation Optional Support customization of share sheet.
  5. Confirm that you have the required dependencies added, as well as any optional ones you would like, and that you have marked the "Status" column in Xcode appropriately.

6. Initialize Branch

This section details how to initialize the Branch SDK depending on the kind of app you have.

The Branch code will vary based on whether you're using SwiftUI, UIKit scenes, or neither.

SwiftUI Apps Not Using Scenes

SwiftUI projects in Xcode no longer come with an AppDelegate by default, so in order to initialize the Branch SDK you will need to create one and reference it from your App.swift file.

  1. Create a new file called AppDelegate.swift in your project's main directory.
  1. Add the following code to your new AppDelegate.swift file:
import SwiftUI

// If using iOS SDK 2.0.0+, use the following import:
import BranchSDK

// If using iOS SDK <2.0.0, use the following import:
// import Branch

class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
        
        Branch.getInstance().initSession(launchOptions: launchOptions) { (params, error) in
            print(params as? [String: AnyObject] ?? {})
            // Access and use deep link data here (nav to page, display content, etc.)
        }
        
        return true
    }
    
}
  1. Add the following code to your App.swift file:
import SwiftUI

// If using iOS SDK 2.0.0+, use the following import:
import BranchSDK

// If using iOS SDK <2.0.0, use the following import:
// import Branch

@main
struct YourAppNameApp: App {
    
    @UIApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL(perform: { url in
                    Branch.getInstance().handleDeepLink(url)
                })
        }
    }
}

Other Apps Not Using Scenes

If your app does not use SwiftUI and also does not use UIKit scenes, update your AppDelegate.swift file with the following code:

import UIKit

// If using iOS SDK 2.0.0+, use the following import:
import BranchSDK

// If using iOS SDK <2.0.0, use the following import:
// import Branch

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  // Use `setUseTestBranchKey(true)` only if you are using your test key
  Branch.setUseTestBranchKey(true)

  // Listener for Branch deep link data
  Branch.getInstance().initSession(launchOptions: launchOptions) { (params, error) in
		print(params as? [String: AnyObject] ?? {})
		// Access and use deep link data here (nav to page, display content, etc.)
  }
  return true
}

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    Branch.getInstance().application(app, open: url, options: options)
    return true
}

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
  	// Handler for Universal Links
    Branch.getInstance().continue(userActivity)
    return true
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
  // Handler for Push Notifications
  Branch.getInstance().handlePushNotification(userInfo)
}
#import "AppDelegate.h"

// If using iOS SDK 2.0.0+, use the following import:
@import BranchSDK;

// If using iOS SDK <2.0.0, use the following import:
// @import Branch;

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  // Use `setUseTestBranchKey(true)` only if you are using your test key
  [Branch setUseTestBranchKey:YES];
  
  // Listener for Branch deep link data
  [[Branch getInstance] initSessionWithLaunchOptions:launchOptions andRegisterDeepLinkHandler:^(NSDictionary * _Nonnull params, NSError * _Nullable error) {
		NSLog(@"%@", params);
		// Access and use deep link data here (nav to page, display content, etc.)
  }];
  return YES;
}

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
  [[Branch getInstance] application:app openURL:url options:options];
  return YES;
}

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler {
  // Handler for Universal Links
  [[Branch getInstance] continueUserActivity:userActivity];
  return YES;
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
  // Handler for Push Notifications
  [[Branch getInstance] handlePushNotification:userInfo];
}

@end

Apps Using Scenes

If your app uses UIKit scenes, you will need to make changes to both your AppDelegate and SceneDelegate files.

  1. In your AppDelegate, update the file to include the following:
import UIKit

// If using iOS SDK 2.0.0+, use the following import:
import BranchSDK

// If using iOS SDK <2.0.0, use the following import:
// import Branch

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
		// Override point for customization after application launch

		// This version of `initSession` includes the source UIScene in the callback
		BranchScene.shared().initSession(launchOptions: launchOptions, registerDeepLinkHandler: { (params, error, scene) in
            
		})
		return true
  }

  func applicationWillTerminate(_ application: UIApplication) {
    // Called when the application is about to terminate
    // Saves data if appropriate
    // See also `applicationDidEnterBackground:` method
  }

  // MARK: UISceneSession Lifecycle

  func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
      // Called when a new scene session is being created.
      // Use this method to select a configuration to create the new scene with
      return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
  }

  func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
      // Called when the user discards a scene session
      // If any sessions were discarded while the application was not running, this will be called shortly after `application:didFinishLaunchingWithOptions`
      // Use this method to release any resources that were specific to the discarded scenes, as they will not return
  }
}
#import "AppDelegate.h"

// If using iOS SDK 2.0.0+, use the following import:
@import BranchSDK;

// If using iOS SDK <2.0.0, use the following import:
// @import Branch;

@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    [[BranchScene shared] initSessionWithLaunchOptions:launchOptions registerDeepLinkHandler:^(NSDictionary * _Nullable params, NSError * _Nullable error, UIScene * _Nullable scene) {
        
    }];

    return YES;
}

- (void)applicationWillTerminate:(UIApplication *)application {
  // Called when the application is about to terminate
  // Save data if appropriate
  // See also `applicationDidEnterBackground:`
}


#pragma mark - UISceneSession lifecycle


- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
    // Called when a new scene session is being created
    // Use this method to select a configuration to create the new scene with
    return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}


- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
    // Called when the user discards a scene session
    // If any sessions were discarded while the application was not running, this will be called shortly after `application:didFinishLaunchingWithOptions`
    // Use this method to release any resources that were specific to the discarded scenes, as they will not return
}

@end
  1. Once your AppDelegate is updated, add the following to your SceneDelegate:
import UIKit

// If using iOS SDK 2.0.0+, use the following import:
import BranchSDK

// If using iOS SDK <2.0.0, use the following import:
// import Branch

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
  var window: UIWindow?
  
  // Use `scene` to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`
  // If using a storyboard, the `window` property will automatically be initialized and attached to the scene
  // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead)
  func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
      guard let _ = (scene as? UIWindowScene) else { return }
    
      // Workaround for SceneDelegate `continueUserActivity` not getting called on cold start:
      if let userActivity = connectionOptions.userActivities.first {
        BranchScene.shared().scene(scene, continue: userActivity)
      } else if !connectionOptions.urlContexts.isEmpty {
        BranchScene.shared().scene(scene, openURLContexts: connectionOptions.urlContexts)
      }
  }
  
  func sceneDidDisconnect(_ scene: UIScene) {
      // Called as scene is being released by the system
      // Happens shortly after the scene enters background, or when its session is discarded
      // Releases any resources associated with this scene that can be re-created the next time the scene connects
      // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead)
  }
  
  func sceneDidBecomeActive(_ scene: UIScene) {
      // Called when the scene has moved from an inactive state to an active state
      // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive
  }
  
  func sceneWillResignActive(_ scene: UIScene) {
      // Called when the scene will move from an active state to an inactive state
      // This may occur due to temporary interruptions (ex. an incoming phone call)
  }
  
  // Use this method to undo the changes made on entering the background
  func sceneWillEnterForeground(_ scene: UIScene) {
      // Called as the scene transitions from the background to the foreground
  }
  
  // Use `sceneDidEnterBackground` to save data and release shared resources
  // Can store enough scene-specific state information to restore the scene back to its current state
  func sceneDidEnterBackground(_ scene: UIScene) {
      // Called as the scene transitions from the foreground to the background

  }
  
  // Note: `willContinueUserActivityWithType` is only required when using SwiftUI & SceneDelegate together
 func scene(_ scene: UIScene, willContinueUserActivityWithType userActivityType: String) {
   scene.userActivity = NSUserActivity(activityType: userActivityType)
   scene.delegate = self
 }
  
  func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
        BranchScene.shared().scene(scene, continue: userActivity)
  }
  
  func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        BranchScene.shared().scene(scene, openURLContexts: URLContexts)
  }
}
#import "SceneDelegate.h"

// If using iOS SDK 2.0.0+, use the following import:
@import BranchSDK;

// If using iOS SDK <2.0.0, use the following import:
// @import Branch;
@interface AppDelegate ()

@interface SceneDelegate ()
@end
@implementation SceneDelegate
	// Use `scene` to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`
	// If using a storyboard, the `window` property will automatically be initialized and attached to the scene
	// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead)
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
  
    // Workaround for SceneDelegate `continueUserActivity` not getting called on cold start
    NSUserActivity *activity = [[connectionOptions userActivities] allObjects].firstObject;

  	if (activity) {
        	[[BranchScene shared] scene:scene continueUserActivity:activity];
     } else if ([[connectionOptions URLContexts] count] != 0) {
        	[[BranchScene shared] scene:scene openURLContexts: [connectionOptions URLContexts]];
     }  
}
- (void)sceneDidDisconnect:(UIScene *)scene {
		// Called as scene is being released by the system
		// Happens shortly after the scene enters background, or when its session is discarded
		// Releases any resources associated with this scene that can be re-created the next time the scene connects
		// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead)
}
- (void)sceneDidBecomeActive:(UIScene *)scene {
    // Called when the scene has moved from an inactive state to an active state
    // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive
}
- (void)sceneWillResignActive:(UIScene *)scene {
    // Called when the scene will move from an active state to an inactive state
    // This may occur due to temporary interruptions (ex. an incoming phone call)
}
- (void)sceneWillEnterForeground:(UIScene *)scene {
    // Called as the scene transitions from the background to the foreground
    // Use this method to undo the changes made on entering the background
}

	// Use `sceneDidEnterBackground` to save data and release shared resources
	// Can store enough scene-specific state information to restore the scene back to its current state
- (void)sceneDidEnterBackground:(UIScene *)scene {
    // Called as the scene transitions from the foreground to the background.
}
- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity {
    [[BranchScene shared] scene:scene continueUserActivity:userActivity];
}
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
    [[BranchScene shared] scene:scene openURLContexts:URLContexts];
}
@end