iOS Universal Link

Overview

Apple introduced Universal Link in their iOS 9 update that redefined the deep linking experience. Deep linking has traditionally been achieved using custom scheme URLs, and while it is still possible to deep link through custom scheme URLs, there have been specific design decisions made by Apple that we have noticed follow the theme of user intent. This theme ultimately informs many of the behavior you see with the changes in the deep linking experience on iOS

Apple's Design

In iOS 8 and older, developers were able to fine tune the path users took in reaching their app. Add the widespread consensus that users of the app produced more conversions, engaged in more sessions, and were far more loyal than those on the web, and you have developers eager to send everyone over to the app (side note - a not so surprising effect of this standard that we’ve noticed is an increase in app only companies, those without web content, or web pages that serve as funnels to the app).

No longer does the developer have free reign to do what they want with the user flow into the app; iOS 9 has not so unjustifiably given control back to their users. Opening custom schemes now produce popups. Redirects behind the scenes now produce popups. App detections methods were killed, and fallback solutions now produce popups. The seamless user experience developers have been accustomed to are now a thing of the past. Unless of course, you do it Apple’s way.

App Detection

Before iOS 9, there were a myriad of ways to do 100% app detection. At Yozio, we used an iframe to open the app in the background. If it opened successfully, the app would take the foreground; if it didn’t, the iframe would simply die in the background. Meanwhile the original webpage detects whether the app has taken the foreground (pageVisibilityHasChanged) and if it hasn’t, the app store will open.

Now the nefarious folk out there will realize that there are some sneaky things you can do with 100% app detection. For example, one well known app polled their users’ installed apps by simply going through the list of top 50 apps in the app store at the time. It would see whether it could open them and compile a list that would then be used to tailor advertisements sent to the user. We have a suspicion that Apple saw this as an unintended capability that ultimately informed a large part of their design choices

How custom scheme has changed

So no app detection means that the only solutions left relies on fallback - attempt to open the app, and if that doesn’t work, it means that they don’t have it, so take ‘em to the app store. That’s okay, there are still clever background processes we can run to prevent the user from seeing that we can’t tell if they have the app. Apple won’t be tricked so easily: any attempt in the background to redirect a user to somewhere they didn’t expect is now met with a popup. We’re painfully aware of the “cannot open in Safari”, “open in app”, or “open in app store” popups. Any hope for a completely frictionless redirect using custom scheme is essentially quashed.

Universal Link comes to the rescue. With iOS 9, Apple provided a solution that lets developers keep their seamless redirect experience (aka no “open in app” popup). However, keeping in line with the theme of user control, Apple ensures there are avenues to your web content available to the users. One of these avenues comes in the form of what we at Yozio colloquially call the “forward” button. Additionally, any attempt to use custom scheme URLs to open the app is paired with an “Open in app?” popup. Both methods of opening the app using a link now provide an option for users to skip the app, and head to web content. In fact, any time a user expresses what Apple interprets as high intent to see web content, they will be taken to the web page the link originally pointed to. This includes typing the URL into the address bar, tapping a bookmark, or clicking a Universal Link on a domain belonging to the same Universal Link. Indeed, Apple has been thorough in making sure that a user has the option to see your web content if they choose to skip the app.

apple_universal_link

Yozio’s Design

With all this in mind, we at Yozio designed our Universal Link solution with flexibility and ease of use as key features; we try to give you as much control as possible in determining your user flow. We’re confident that we’ve our solution will fit your needs.

In this solution, the SuperLink is the Universal Link; we host the app association file, and the domain registered in the app as the app link/associated domain is r.yozio.com. By choosing this solution, you have the most granular control over how your users are redirected. By default, those without the app will be taken to the app store, and those with the app will be deep linked into your app via Universal Link. We will attempt to redirect users who click the “forward” button back to the app via custom scheme. If they still refuse, they will see a blank landing page with Apple’s Universal Link native “Open in app” banner. You can disable the custom scheme “fallback”, as well as provide us a custom landing page that we will redirect users who click the forward button to. By default, with this solution, since the SuperLink is the Universal Link, users will see r.yozio.com as the destination URL of the “forward” button. If you are using custom domain and would like your custom domain to act as the Universal Link, you must implement our HTTPS custom domain feature.

Setup

yozio_universal_link_default

Integration Steps

The first step to implementing Yozio's support for Universal Link is to set up the Yozio SuperLink to open your app via Universal Link. This will include adding the Yozio SuperLink domain as an associated domain to your app (so the app recognizes the SuperLink as a Universal Link) and entering your bundle id and app id prefix so that we can create an entry in our apple-app-site-association-file.

In order for you to use your custom domain SuperLinks, and for your brand/domain to appear in the destination URL of the “forward” button, you will need to implement HTTPS custom domain. You can put in a request for HTTPS custom domain by going to Yozio Console > Settings > General and entering the domain that you'd like to register as your HTTPS custom domain.

If you do not implement HTTPS custom domain, you can still use r.yozio.com/short_url as the Universal Link.

In Xcode, under Capabilities, add applinks:r.yozio.com and applinks:r.yoz.io (or your custom HTTPS domain, i.e. applinks:your.custom.domain) as an associated domain. This will allow your app to be opened when a user clicks on your SuperLink.

Note: Do NOT add applinks:deeplink.yozio.com as an associated domain. Not only is the deeplink.yozio.com domain not configured for Universal Links, Universal Links is not supported when redirected to; the Universal Link must physically be tapped on to trigger your app and deeplink.yozio.com is only accessible by redirect from a Yozio SuperLink. Adding applinks:deeplink.yozio.com is not expected to work.

3. Enter your bundle id and app id prefix in the Yozio Console.

This will tell us to generate an entry in our apple-app-site-association JSON file for your app. To do this, go to the Yozio Console > Settings > iOS Universal Links. Once there, enter your App ID Prefix (for most, this will be the Apple Developer Team ID), your iPhone bundle id, and your iPad bundle id. Verify that all of these are correct, and hit update settings. Yozio will then generate the App Association JSON file.

Check out this article to see if you're App ID prefix differs from your Apple Team ID

You can now test whether the SuperLink has been properly configured as a Universal Link into your app. Simply click on a Yozio SuperLink (one that uses the domain you entered as an associated domain to your app) and see if the app opens directly.

If the popup "Open in App?" appears, this means that the SuperLink has not been configured correctly as a Universal Link. Double check that you have added the correct domain, and that you have "Associated Domains" enabled in your developer profile. Additionally, verify that the bundle id and app id prefix that you have entered are correct.

If the SuperLink still does not Universal Link into your app, please email us at [email protected]. Please include as much information as possible regarding your integration in the email, as this will expedite the debugging process.

In order to support metadata passing from the SuperLink click to your app, and to support event tracking to the Yozio Console, follow these two steps:

5. Integrate the Yozio SDK v2.1 or newer.

SDK v2.1 is designed to be Xcode 7 compatible. Additionally, due to the nature of Universal Links and how it deep links, this SDK is required for static metadata to be passed into the app. Dynamic metadata is passed as usual.

6. Add the restorationHandler code block

In order to track your SuperLinks and their metadata (including for example, the Universal Link that you will pass to Yozio as metadata), you'll need to add a restorationHandler to your appDelegate. Inside the restorationHandler, you need to check if the user activity type is NSUserActivityTypeBrowsingWeb, which means the user has been deep linked into your app via Universal Link. If so, you can call [Yozio handleDeeplinkURL:url withAssociatedDomains:array_of_custom_domains deeplinkMetaDataCallback:callback] function to a track deep link with Yozio (and get Yozio Deep Link Drill Down Metrics in your Yozio Dashboards) and call Yozio getMetaDataFromDeeplink to retrieve the metadata as dictionary.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
- (BOOL)application:(UIApplication *)application
    continueUserActivity:(NSUserActivity *)userActivity
     restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler
    {
        if ([NSUserActivityTypeBrowsingWeb isEqualToString: userActivity.activityType]) {

            NSString *yozioDomain  = @"r.yoz.io";
            NSString *customDomain = @"custom-domain.yozio.com";

            // Initialization with metadata callback
            [Yozio handleDeeplinkURL:userActivity.webpageURL
               withAssociatedDomains:@[yozioDomain, customDomain]
            deeplinkMetaDataCallback:^(NSDictionary *metaData)
             {
                 NSLog(@"%@ Got Meta Data from the deeplink: %@", NSStringFromSelector(_cmd), metaData);
                 [Utils launchMainViewControllerWithMetaData:metaData];
             }];
        }

        return YES;
    }

Customize your user flow

One of the more powerful capabilities of setting up the Yozio SuperLink as a Universal Link into your app is that you can fine tune your users experience when they click on a SuperLink. Specifically, you can control where the user is redirected when the click on the "forward" button.

You have two options for configuring the user flow - via the Yozio Console, by selecting the desired flow in your SuperLink's Redirect Settings, or via metadata, using the keys yozio_use_custom_scheme_in_safari and yozio_ios_universal_link_redirect_url.

Universal_Link_redirect_settings

Go to the SuperLink Edit page by logging into the Yozio Console and navigating to SuperLinks > Organic Links and clicking Edit on the SuperLink you want to configure. Alternatively, you can navigate to Settings > Default Redirect Settings > iPhone/iPad to set the user flow for all your SuperLinks.

8. Set yozio_use_custom_scheme_in_safari (OPTIONAL)

For users who click the "forward" button, you can attempt to redirect them to your app a second time using custom scheme. This flag is by default set to true. If you’d like to set it to false, simply pass as metadata yozio_use_custom_scheme_in_safari=false. Note that by leaving this set to true, if your user ever clicks on the “forward” button, they will never be Universal Linked through this SuperLink again. This is because since we fallback using custom scheme, the user will never have the opportunity to click the “open in app” banner, and “re enable” Universal Link.

yozio_universal_link_custom_scheme_false

Note: Setting this key will cause whatever user flow you set in your Redirect Settings to be overridden

This is an optional parameter used to provide to us the webpage you’d like users redirected to when they click the forward button. By default, this is not set, and users will be redirected to a blank landing page displaying the “open in app” banner. Note that if you set this, your users will go to the landing page, and they will not be able to see the “open in app” banner on your webpage, unless the webpage is also a Universal Link domain for your app.

yozio_universal_link_custom_scheme_false_custom_web_page

Note: Setting this key will cause whatever user flow you set in your Redirect Settings to be overridden

Universal_Link_config_2

Go to the Yozio Console and navigate to Settings > iOS Universal Links. There, select Yes for all domains you've added as an associated domain to your app. This will enable the user flows that you've set. Do NOT set this until you've verified that your Universal Links work as expected, as this will alter the flow of your SuperLinks currently in production. Make sure to set this for both iPhone and iPad (the reason we have it separate is that some users have a separate iPad app, or they do not serve their iPhone app to their iPad users. If you are using the same iPhone app to serve your iPad users, go ahead and enable the Universal Link flow for iPad on the Yozio Console as well).

If you are using a custom domain for your SuperLinks, make sure that you implement Yozio's support for HTTPS custom domain. If you do not implement HTTPS custom domain and you enable Universal Links, your SuperLinks using a custom domain will not deep link using Universal Links.

Notes

  • In order to use your custom domain SuperLinks as the Universal Link, you must implement HTTPS custom domain
  • In order for your domain/branding to be displayed on the destination URL of the forward button, you must implement HTTPS custom domain.
  • This feature is an app level setting; all of your SuperLinks will act as Universal Links into your app.
  • If you set yozio_ios_universal_link_redirect_url, deploy our the Yozio Web Snippet to help better handle users.
  • We've recently found that Universal Link will not trigger when the third party app uses a Safari View Controller (an in app browser) to open the SuperLink. Instead, the SuperLink will be opened using a web view, and the fallback flow is followed. This means in order to deep link your users on these third party apps, you will need to turn on "custom scheme fallback", which will configure your SuperLinks to attempt to deep link the user with custom scheme when Universal Link fails.

Testing

With your latest app installed, click on a SuperLink to test if the Universal Link is working as expected. You should not see any popups, and you should go straight to the app. Once there, you should be able to see the “forward” button. If you’ve set up HTTPS custom domain, you should see your custom domain there. If not, you should see “r.yozio.com”. If you click the forward button and you’ve set yozio_use_custom_scheme_in_safari to false, you should either see a blank landing page with the open in app banner displayed, or your own custom landing page if you’ve provided one. If you’ve left yozio_use_custom_scheme_in_safari as true, then you should see an “Open in app” popup. Selecting no will take you through the landing page flow described earlier.