App Links on iOS

An interesting aspects of sharing to Facebook from your app is that when people engage with the news feed stories posted from your app. Those stories can send people to your app or your app's App Store page which drives traffic and app installs. You can implement this behavior using App Links.

When you set up App Links, you can control what happens when someone taps on one of the links shared through your app or on the story attribution (name of your app) in one of the Open Graph stories shared through your app. If your app has web content, people see a web view of that content.

If your app is installed there may be an Open button that launches your iOS app. If your app isn't installed, people see an install option to directing them to your app's App Store page. If your app is mobile-only and has no web content, when someone clicks the shared link they either open your app if it's installed or go to your app's App Store page (if your app isn't installed). The image below shows this flow:

App Links for iOS doesn't support deferred deep linking for App Invites, so you can't open content other than the starting screen once people have installed the app.

In the following sections we will explain how to handle incoming links once you've set up your App Links.

Handling incoming links

When someone taps a link posted from your app or taps the app attribution in an Open Graph story posted from your app in Facebook for iOS, they may be presented with the option to open your content in your iOS app. Alternatively, they may be immediately directed to your app. If your app is mobile only, set should_fallback=false so that if people don't have your app installed, they will be taken to the App Store to download your app. The iOS app link for your content will be sent to your app. To ensure an engaging user experience, you should process the incoming link when your app is activated and direct the person to the object featured in the story they're coming from.

The link your app will receive will look like this:

[url]?al_applink_data=JSON_ENCODED_DATA

Where url is the incoming URL based on a custom scheme that you've defined for your app. You'll also receive an al_applink_data query parameter with JSON_ENCODED_DATA content that looks something like this:

{
    "target_url": "https://www.example.com/abc.html",
    "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"
    }
}

Where fb_access_token and fb_expires_in are only available if the person has authenticated with Facebook in your app.

You can then override the application:openURL:sourceApplication:annotation: method in your app delegate implementation file to customize how your app handles these incoming urls.

The Bolts Framework , which is included in Facebook SDK, provides easy to use APIs to help you to parse the incoming URL.

In the code sample below, we're simply displaying an alert to the person, but you should direct people through the appropriate flow for your app:

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
    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]
                                   delegate:nil
                          cancelButtonTitle:@"OK"
                          otherButtonTitles:nil] show];
    }
    ...
}

Adding back navigation

When your app is launched as a result of an app link, you should provide people a way to navigate back to the original app. In our scenario, people should be able to get back to the Facebook for iOS app. The App Links standard describes the expected back navigation flow. When your app is launched, a referer_app_link parameter is provided as part of the incoming URL. The launching app's name is also provided. You can use these two pieces of data to construct the back navigation and present a view that the person can interact with.

The Bolts Framework provides a mechanism you can use to easily add the back navigation view controller and corresponding back navigation view:

// AppDelegate.h
@property (strong, nonatomic) BFURL *parsedUrl;

// AppDelegate.m
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
    
    // Parse and save the URL using Bolt
    BFURL *parsedUrl = [BFURL URLWithURL:url];
    self.parsedUrl = parsedUrl;
    ...
 }
 
// ShareViewController.m
@property (weak, nonatomic) BFAppLinkReturnToRefererView *appLinkReturnToRefererView;
@property (strong, nonatomic) BFAppLink *appLink;
...

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    if (self.appLinkReturnToRefererView) {
        self.appLinkReturnToRefererView.hidden = YES;
    }
    AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    if (delegate.parsedUrl) {
        self.appLink = [delegate.parsedUrl appLinkReferer];
        [self _showRefererBackView];
    }
    delegate.parsedUrl = nil;
    
}

- (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];
}

If you wanted to implement your own back button, here's an example of how you would implement it. First store the referer info when the app link is processed:

// AppDelegate.h
@property (strong, nonatomic) NSDictionary *refererAppLink;

// AppDelegate.m
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
    ...
    BFURL *parsedUrl = [BFURL URLWithInboundURL:url sourceApplication:sourceApplication];
    NSDictionary *appLinkData = [parsedUrl appLinkData];
    
    if (applinkData) {
        // Save the referer link info
        self.refererAppLink = applinkData[@"referer_app_link"];
        ...
    }
    ...
}

Then you use this info to set up a way for the person to get back to Facebook for iOS. In the example below, a UIView is set up if a referer link is found in the app delegate. This view is set up with a UITapGestureRecognizer to process taps from the person and launch the referer link if it can be opened:

// ShareViewController.m

@interface ShareViewController () <UIGestureRecognizerDelegate>
...
@property (strong, nonatomic) NSDictionary *backLinkInfo;
@property (weak, nonatomic) UIView *backView;
@property (weak, nonatomic) UILabel *backLinkLabel;
...
@end

@implementation ShareViewController
...
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    if (delegate.refererAppLink) {
        self.backLinkInfo = delegate.refererAppLink;
        [self _showBackLink];
    }
    delegate.refererAppLink = nil;
    
}

- (void) _showBackLink {
    if (nil == self.backLinkView) {
        // Set up the view
        UIView *backLinkView = [[UIView alloc] initWithFrame:
                                CGRectMake(0, 30, 320, 40)];
        backLinkView.backgroundColor = [UIColor darkGrayColor];
        UILabel *backLinkLabel = [[UILabel alloc] initWithFrame:
                                  CGRectMake(2, 2, 316, 36)];
        backLinkLabel.textColor = [UIColor whiteColor];
        backLinkLabel.textAlignment = NSTextAlignmentCenter;
        backLinkLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:14.0f];
        [backLinkView addSubview:backLinkLabel];
        self.backLinkLabel = backLinkLabel;
        [self.view addSubview:backLinkView];
        self.backLinkView = backLinkView;
    }
    // Show the view
    self.backLinkView.hidden = NO;
    // Set up the back link label display
    self.backLinkLabel.text = [NSString
                               stringWithFormat:@"Touch to return to %@", self.backLinkInfo[@"app_name"]];
    // Set up so the view can be clicked
    UITapGestureRecognizer *tapGestureRecognizer =
    [[UITapGestureRecognizer alloc] initWithTarget:self
                                            action:@selector(_returnToLaunchingApp:)];
    tapGestureRecognizer.numberOfTapsRequired = 1;
    [self.backLinkView addGestureRecognizer:tapGestureRecognizer];
    tapGestureRecognizer.delegate = self;
}

- (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;
}