How To Implement Deep Linking on iOS

One of the greater pains mobile developers experience is trying to more closely relate native iOS apps. That's where deep linking comes in, a capability that a number of tools can enable. Here we compare and contrast three such tools: Facebook's AppLinks, Tapstream's Deferred Linking and Button's DeepLink SDK. (Apple will soon have a horse in this race; stay tuned.)

There are certainly many times when your organization would want to enable deep linking. Say you want to associate or pass certain responsibilities to another app, or you have built a suite of utility apps and you want to direct a user from one app to another app, passing in specific information in a contextually sensitive way. Maybe you want to enable users to navigate from a contact in your app directly to his or her LinkedIn profile. Sure, you could just provide a URL, but that would bring up a browser with the Web version of the app instead of the native LinkedIn app. With deep linking, developers can set up apps so that they contextually redirect a user to a precise location in another app. This is done through the enveloping of a Uniform Resource Identifier (URI) that marries a very specific location address, formatted similar to:


The idea is to encapsulate vital information in a calculated and intentional way to allow external applications (or even Web pages) to open up another native app and present the specific location within the app that the URI refers to. This contextual solution provides a way around the closed ecosystem in platforms like iOS, as well as greater cross-application Integration.

Android has supported deep linking for quite some time, and Android’s Chrome browser search results even deep link to certain apps.


App Links By Facebook

App Links is a deep-linking standard by Facebook that superseeds the company's deprecated Deep Linking with iOS. Gaining wide community attention thanks to the backing of Facebook, App Links allows for content, whether in a Facebook Feed or another App Links-enabled app, to jump directly to a specific location within the app.


Source: (Facebook)

The above illustrates the workflow, whereby a person for instance would see your content on a Facebook feed (or another app or even a Web page), which has a provided App Link meta-data.

  1. The user selects the App Link meta-data;
  2. Facebook looks up the content (or, if it is a web-page, adding some extra metadata) and determines what app should be launched through a directory Facebook maintains for public web urls.
  3. Facebook then launches your app with the contextual data appended (i.e., specific profile or any other location information) to load content directly. If the user has not installed your app, it would then load a Web page.

Getting started with AppLinks

For our example we will refer to an AppLink from one of our Web pages that we host. So, within the header, a fictitious ProgrammableWeb app, we would register in the header the meta data as follows:

    <meta property="al:ios:url" content="programmableweb://news/1331" />
    <meta property="al:ios:app_store_id" content="44492821" />
    <meta property="al:ios:app_name" content="PPW for iOS App" />
    <meta property="og:title" content="ProgrammableWeb News" />

In the first line above, you can see we are referring to a specific link:


Within our fictitious iOS app, we would have defined the url in the .plist file, but if the user hasn’t installed the app, it would fall back to the url /news/1311, which was derived from the programmableweb://news/1331 meta-data.

For those who don't have a website with Web content, and thus public Web URLs, there is the option of using Facebook’s Mobile Hosting API. This allows users to  manage your App Links; you can get started on iOS by entering the following into CURL (in terminal):

curl  HTTPS:// \
-F access_token="APP_ACCESS_TOKEN" \
-F name="ProgrammableWeb for iOS Example" \
-F ios=' [
      "url" : "programmableweb://news/1331",
      "app_store_id" : 44492821,
      "app_name" : "PPW for iOS App",
  ]' \
-F web=' {
    "should_fallback" : false,

We would get an id returned back in JSON format:


You can subsequently retrieve your new App Links URI through another curl request, by passing in the id returned in the previous step:

curl -G \
-d access_token="APP_ACCESS_TOKEN" \
-d fields=canonical_url \
-d pretty=true

There’s one cool benefit worth mentioning:  the ability to customize the fallback to redirect users to the App Store to download your app if they haven't installed your app and have selected the deep link. The user would then get directed to the appropriate deep link, with the content passed in, not breaking the engagement chain of events.

Your app would receive a JSON-encoded data packet similar to the following:

    "target_url": "",
    "extras": {
        "fb_app_id": [YOUR_FACEBOOK_APP_ID],
        "fb_access_token": "[ACCESS_TOKEN']",
        "fb_expires_in": "3600"
    "referer_app_link": {
        "url": "[FACEBOOK_APP_BACK_LINK]",
        "app_name": "Facebook"

You then override in your AppDelegate class, the application:openURL:sourceApplication:annotation: method to customise how you handle the parsed incoming App Link request. We recommend using for iOS the low-level Bolts Library Framework, which will help with reactive and event-driven request management.

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
    return [FBAppCall handleOpenURL:url
                    fallbackHandler:^(FBAppCall *call) {
                        BFURL *parsedUrl = [BFURL URLWithInboundURL:url sourceApplication:sourceApplication];
                        if ([parsedUrl appLinkData]) {
                            // this is an applink url, handle it here
                            NSURL *targetUrl = [parsedUrl targetURL];
                            [[[UIAlertView alloc] initWithTitle:@"Received link:"
                                                        message:[targetUrl absoluteString]
                                              otherButtonTitles:nil] show];

Navigating back to the app

App Links can also give the users the ability to navigate back to the referred app. You noticed in the code snippet above:

 "referer_app_link": {
            "url": "[FACEBOOK_APP_BACK_LINK]",
            "app_name": "Facebook"

It is in fact good UX practice to allow users to navigate their way back to the app, and App Links provides as part of the incoming JSON packet both the launching app’s name and URL, allowing you to derive the back-navigation required. We handle returning the user with a lot of flexibility, but the first thing you need to do is store the referrer info we got in the AppDelegate:

if (!error &&
                 [applinkData isKindOfClass:[NSDictionary class]] &&
                 applinkData[@"target_url"]) {
                 // Save the referer link info
                 self.refererAppLink = applinkData[@"referer_app_link"];
                 NSString *targetURLString = applinkData[@"target_url"];

Then in the target view controller, add an action to call a method similar to the following:

- (void)_returnToLaunchingApp:(id)sender {
    // Open the app corresponding to the back link
    NSURL *backLinkURL = [NSURL URLWithString:self.backLinkInfo[@"url"]];
    if ([[UIApplication sharedApplication] canOpenURL:backLinkURL]) {
        [[UIApplication sharedApplication] openURL:backLinkURL];
    self.backLinkView.hidden = YES;

There are other best practices you can follow, such as constructing an informative view before calling the method above. Facebook recommends adding a navigation bar on the top, as illustrated below:


An even easier method recommended by Facebook is to once again leverage the Bolts framework, which would implement something like the above view:

- (void) _showRefererBackView {
    if (nil == self.appLinkReturnToRefererView) {
        // Set up the back link navigation view
        BFAppLinkReturnToRefererView *backLinkView  = [[BFAppLinkReturnToRefererView alloc] initWithFrame:CGRectMake(0, 30, 320, 40)];
        self.appLinkReturnToRefererView = backLinkView;
    self.appLinkReturnToRefererView.hidden = NO;
    // Initialize the back link view controller
    BFAppLinkReturnToRefererController *alc =[[BFAppLinkReturnToRefererController alloc] init];
    alc.view = self.appLinkReturnToRefererView;
    // Display the back link view
    [alc showViewForRefererAppLink:self.appLink];

Be sure to read the next Mobile article: How to Get Started With Apple's ResearchKit