In-app deep link routing

Overview

When a Branch link is opened, either your app launches or users are taken to the App/Play store to download it. Deep links improve this process by routing users directly to specific content after your app launches. With Branch, this still works even if users have to stop and download the app first (a.k.a., "deferred deep links").

Deep links are an incredibly important part of delivering a high quality user experience. With deep links, you can take users to the exact thing they clicked on or even offer a customized onboarding experience.

Option 1: Build custom routing inside the routing callback

Route immediately on app open

Inside the deep link handler callback that you register in initSession, you will want to examine the params dictionary to determine whether the user opened a Branch link. Below is an example assuming that the links correspond to pictures. Below are some examples from iOS and Android where we're using the pictureId key to route, but you can see more code snippets for the other platforms here.

  • iOS - Objective C

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
      // initialize the session, setup a deep link handler
      [[Branch getInstance] initSessionWithLaunchOptions:launchOptions
                              andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) {
    
        // start setting up the view controller hierarchy
        UINavigationController *navC = (UINavigationController *)self.window.rootViewController;
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
        UIViewController *nextVC;
    
        // If the key 'pictureId' is present in the deep link dictionary
        // then load the picture screen with the appropriate picture
        NSString *pictureId = [params objectForKey:@"pictureId"];
        if (pictureId) {
          nextVC = [storyboard instantiateViewControllerWithIdentifier:@"PicVC"];
          [nextVC setNextPictureId:pictureId];
        } else {
          nextVC = [storyboard instantiateViewControllerWithIdentifier:@"MainVC"];
        }
    
        // navigate!
        [navC setViewControllers:@[nextVC] animated:YES];
      }];
    
      return YES;
    }
    
  • iOS - Swift

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        let branch: Branch = Branch.getInstance()
            branch.initSession(launchOptions: launchOptions, andRegisterDeepLinkHandler: {params, error in
            // If the key 'pictureId' is present in the deep link dictionary
            if error == nil && params["+clicked_branch_link"] != nil && params["pictureId"] != nil {
                print("clicked picture link!")
                // load the view to show the picture
            } else {
                // load your normal view
            }
        })
        return true
    }
    
  • Android

    @Override
    public void onStart() {
        super.onStart();
    
        Branch branch = Branch.getInstance();
    
        branch.initSession(new BranchReferralInitListener(){
            @Override
            public void onInitFinished(JSONObject referringParams, Branch.BranchError error) {
                if (error == null) {
                    // params are the deep linked params associated with the link that the user clicked before showing up
                    // params will be empty if no data found
                    String pictureID = referringParams.optString("picture_id", "");
                    if (pictureID.equals("")) {
                        startActivity(new Intent(this, HomeActivity.class));
                    }
                    else {
                        Intent i = new Intent(this, ViewerActivity.class);
                        i.putExtra("picture_id", pictureID);
                        startActivity(i);
                    }
                } else {
                    Log.e("MyApp", error.getMessage());
                }
            }
        }, this.getIntent().getData(), this);
    }
    

Branch-added parameters

In addition to any custom key/value pairs specified in the link data dictionary, Branch also returns some other useful parameters every time a session is initialized. These parameters will be returned every time initSession is called, even if the user has not clicked on a Branch link. Here is a list, and a description of what each represents.

  • ~ denotes analytics
  • + denotes information added by Branch
  • (for the curious, $ denotes reserved keywords used for controlling how the Branch service behaves. Read more about control parameters on the Configuring Links page)
Parameter Meaning
+is_first_session Denotes whether this is the first session (install) or any other session (re-install, open)
+clicked_branch_link Denotes whether or not the user clicked a Branch link that triggered this session
+match_guaranteed True or false as to whether the match was made with 100% accuracy
+referrer The referrer for the link click, if a link was clicked
+click_timestamp Epoch timestamp of when the click occurred
+url The full URL of the link that drove the install/open, if present (e.g. yourapp.app.link/abcde12345)
+phone_number The phone number of the user, if the user texted himself/herself the app
~channel The channel on which the link was shared, specified at link creation time
~feature The feature, such as invite or share, specified at link creation time
~tags Any tags, specified at link creation time
~campaign The campaign the link is associated with, specified at link creation time
~stage The stage, specified at link creation time
~creation_source Where the link was created ('API', 'Dashboard', 'SDK', 'iOS SDK', 'Android SDK', or 'Web SDK')
~id Automatically generated 18 digit ID number for the link that drove the install/open, if present (0 for dynamic and 3P links)

You can retrieve the deep link data at any time from the Branch singleton by calling one of the below methods. This would be the route to use if you wanted to deep link the user after prompting them to log in or something. You can see the code snippets for other platforms here.

Get latest session referring params

This returns the latest set of deep link data from the most recent link that was clicked. If you minimize the app and reopen it, the session will be cleared and so will this data.

  • iOS - Objective C

    NSDictionary *params = [[Branch getInstance] getLatestReferringParams];
    
  • iOS - Swift

    let sessionParams = Branch.getInstance().getLatestReferringParams()
    
  • Android

    JSONObject sessionParams = Branch.getInstance().getLatestReferringParams();
    

Get first session referring params

This returns the first set of deep link data that ever referred the user. Once it's been set for a given user, it can never be updated. This is useful for referral programs.

  • iOS - Objective C

    NSDictionary *params = [[Branch getInstance] getFirstReferringParams];
    
  • iOS - Swift

    let firstParams = Branch.getInstance().getFirstReferringParams()
    
  • Android

    JSONObject installParams = Branch.getInstance().getFirstReferringParams();
    

If your app already supports deep linking using URI paths, you can populate the $deeplink_path, $ios_deeplink_path or $android_deeplink_path link parameters with the URI path of the content to be displayed within the app. When the Branch SDK receives a link containing one of these parameters it will automatically load the specified URI path.

Incomplete support on iOS

Universal Links and Spotlight do not support deep linking via URI paths. If you use $deeplink_path or $ios_deeplink_path, you will need to implement some custom logic. Click here for more information.

All of the examples below create links that will cause Branch to display myapp://content/1234 after launch.

When creating links dynamically

If you're creating a link by appending query parameters, just append the control parameters to the URL. Please make sure to URL encode everything, lest the link will break.

"https://[branchsubdomain]?%24deeplink_path=content%2F1234"

When using a mobile SDK

  • iOS - Objective C

    BranchLinkProperties *linkProperties = [[BranchLinkProperties alloc] init];
    linkProperties.feature = @"sharing";
    linkProperties.channel = @"facebook";
    [linkProperties addControlParam:@"$deeplink_path" withValue:@"content/1234"];
    
  • iOS - Swift

    let linkProperties: BranchLinkProperties = BranchLinkProperties()
    linkProperties.feature = "sharing"
    linkProperties.channel = "facebook"
    linkProperties.addControlParam("$deeplink_path", withValue: "content/1234")
    
  • Android

    LinkProperties linkProperties = new LinkProperties()
                   .setChannel("facebook")
                   .setFeature("sharing")
                   .addControlParameter("$deeplink_path", "content/1234");
    

When creating Quick Links on the Branch dashboard

You can specify the control parameters for individual Quick Links by inserting the keys and values into the Deep Link Data (Advanced) section.

image

Because Universal Links, Spotlight and Android App Links do not use URI schemes for deep link routing. If you populate $deeplink_path, $ios_deeplink_path or $android_deeplink_path with a URI path, you will need to a bit of additional work to ensure that Branch links route according to your original schema.

  1. Call initSession as described in the app configuration steps
  2. In the callback function, add some custom code to read the appropriate $deeplink_path parameter in the params
  3. Use this value to call your existing routing logic to route users to the correct place in your app

Auto-routing in iOS

Open the view controller that you want to appear when a user clicks a link. For example, this could be a view to show a product. First, import the Branch framework:

  • Objective C

    #import "Branch.h"
    
  • Swift

    import Branch
    

Register your view controller for the delegate BranchDeepLinkingController:

  • Objective C

    @interface ExampleDeepLinkingController : UIViewController <BranchDeepLinkingController>
    
  • Swift

    class ExampleDeepLinkingController: UIViewController, BranchDeepLinkingController {
    

Receive the delegate method that will be called when the view controller is loaded from a link click:

  • Objective C

    @synthesize deepLinkingCompletionDelegate;
    - (void)configureControlWithData:(NSDictionary *)data {
        NSString *pictureUrl = data[@"product_picture"];
    
        // show the picture
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:pictureUrl]];
            UIImage *image = [UIImage imageWithData:imageData];
            dispatch_async(dispatch_get_main_queue(), ^{
                self.productImageView.image = image;
            });
        });
    }
    
  • Swift

    func configureControl(withData params: [AnyHashable: Any]!) {
        let dict = params as Dictionary
        if dict["product_picture"] != nil {
           // show the picture
        }
    }
    

What is a link data key?

The example key product_picture is a parameter from the data dictionary of the link that was clicked, and would have been defined when the link was created.

  • Objective C
- (IBAction)closePressed {
    [self.deepLinkingCompletionDelegate deepLinkingControllerCompleted];
}
  • Swift
var deepLinkingCompletionDelegate: BranchDeepLinkingControllerCompletionDelegate?
func closePressed() {
    self.deepLinkingCompletionDelegate!.deepLinkingControllerCompleted()
}

Lastly, you need to tell Branch about the view controller you just configured, and which key it is using from the link's data dictionary.

  • Objective C

    [branch initSessionWithLaunchOptions:launchOptions andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) {
        if (!error && params) {
            // params are the deep linked params associated with the link that the user clicked -> was re-directed to this app
            // params will be empty if no data found
            // ... insert custom logic here ...
            print(@"params: %@", params.description);
        }
    }];
    
  • Swift

    branch.initSession(launchOptions: launchOptions, deepLinkHandler: { params, error in
        if error == nil {
            // params are the deep linked params associated with the link that the user clicked -> was re-directed to this app
            // params will be empty if no data found
            // ... insert custom logic here ...
            print("params: %@", params.description)
        }
    })
    

Remove it, and insert this snippet in the same place:

  • Objective C

    ExampleDeepLinkingController *controller = [[UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:@"DeepLinkingController"];
    
    [branch registerDeepLinkController:controller forKey:@"product_picture" withPresentation:BNCViewControllerOptionShow];
    [branch initSessionWithLaunchOptions:launchOptions automaticallyDisplayDeepLinkController:YES];
    
  • Swift

    var controller = UIStoryboard.init("Main", NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("DeepLinkingController")
    
    branch.registerDeepLinkController(controller, forKey: "product_picture", withPresentation: .optionShow)
    branch.initSession(launchOptions: launchOptions, automaticallyDisplayDeepLinkController: true)
    

Now whenever your app launches from a Branch link that has the product_picture key set in its data dictionary, the ExampleDeepLinkingController view controller will be displayed!

Option Meaning
BNCViewControllerOptionShow This option pushes view controller onto the navigation stack in a similar way as the showViewController
BNCViewControllerOptionPush This option pushes view controller onto the navigation stack in a similar way as the pushViewController
BNCViewControllerOptionPresent This option presents view controller onto the root view controller of window in a similar way as the presentViewController

Note

BNCViewControllerOptionShow or BNCViewControllerOptionPush option would only push a view controller if the root view controller of window is of type UINavigationViewController. Or else, the view controller would be presented by default.

Auto-routing in Android

Open the Activity that you want to appear when a user clicks a link. For example, this could be an Activity to show a product. Insert the following code snippet to display your content when the Activity is loaded from a link click:

@Override
protected void onResume() {
    super.onResume();
    if (Branch.isAutoDeepLinkLaunch(this)) {
        try {
            String autoDeeplinkedValue = Branch.getInstance().getLatestReferringParams().getString("product_picture");
            launch_mode_txt.setText("Launched by Branch on auto deep linking!"
                    + "\n\n" + autoDeeplinkedValue);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    } else {
        launch_mode_txt.setText("Launched by normal application flow");
    }
}

What is a link data key?

The example key product_picture is a parameter from the data dictionary of the link that was clicked, and would have been defined when the link was created.

Lastly, you need to tell Branch about the Activity you just configured, and which key it is using from the link's data dictionary. In your Manifest file, locate the definition for the Activity above and add this meta-data tag:

<meta-data android:name="io.branch.sdk.auto_link_keys" android:value="product_picture" />

Now whenever your app launches from a Branch link that has the product_picture key set in its data dictionary, this Activity will be displayed!

Comments