iOS 9 Deep Linking using Universal Links

Before Universal Links the primary way to open up apps was by trying to redirect to the app's URI scheme, putting the routing logic in Safari. There was no way to check wether the app was installed or not. Meaning developers would try to open the app using the URI schemes 100% of the time in the off chance the app was not installed and using a timer to fallback to the App Store page.

Universal Links in iOS 9 intended to fix these hacks. Instead first opening Safari first, iOS 9 will check if it's a registered universal link and if the corresponding app is installed. If it is, it will open the app, if it isn't, Safari will open and load the http(s) link there as a fallback. Functionally this allows you to have one link that will either open up the app or open your mobile website.

I'm going to use the Realo mobile app as an example, since I just implemented it here a bit earlier this week. Note that the Realo mobile apps are wrapper apps for now since our product is changing too fast and features are developing too fast to keep a native app in sync. We do have wrapper apps because it provides us with some extra benefits such as push notifications, Facebook login, location services etc. Needless to say, since we have wrapper apps and actually display the website in our apps, this is a perfect use case to open links from mails for example directly with the app instead of the website.

To enable universal links we need to do 3 things: setup both your website and app, so iOS 9 can build a trust between them. And change a few things in the Apple Developer portal. Of course I am asuming you already have a website and app ready.

Apple Developer Portal

Let's start with preparing our app to handle universal links, go to and sign in into your account. Navigate to Certificates, IDs & Profiles and then to App IDs. Select your app and click the Edit button.

Now check Associated Domains and save. That's it for the Apple Developer Portal, easy right? Let's move on to setting up your website, but don't close Apple Developer yet. We still need to copy some information over in the next step.


Website setup

Setting up your website is very easy. The only thing you need to do is upload a json file called apple-app-site-association, note that it's lacking the .json extension but does need to be served with the application/json content type. This file is also required to be served over https but with services such as Let's Encrypt and CloudFlare this can be done with a few clicks for free, so that shouldn't be too big of an issue.

This is the apple-app-site-association json file that we're serving at Realo. You can just copy this over for now, place it in the root of your website so it is accessible like here:

    "applinks": {
        "apps": [ ],
        "details": [
                "appID": "",
                "paths": [ "*" ]

The value of appID above is the App Prefix glued together with the App ID separated with a single dot between them.
Change the value so it matches your App Prefix and your App ID. Y5KUUS7MK8 + . + =


App setup

And as a last step we need to setup the app and handle the incoming universal links so we can show the right content to the user.

Associated Domains

As we previously enabled Associated Domains on Apple Developer, we now also need to enable this in your app. Open up your app in Xcode, select your target and navigate to the Capabilities tab. Scroll down to Associated Domains and enable this.


Now add all your domains you want to enable for deep linking prefixed with applinks: like so:


Normally if all goes well, if you click a link (from any app, like Mail, Messages, Safari..) with one of the domains you provided, the app should open. If this is not happening it's possible you missed something or something went wrong before.

Of course, when a user clicks a link, you want to handle this in the app. Show them the correct content, perform a specific action, tracking/logging, .. So let's open up your AppDelegate.m and add the following delegate. Change the logic as you please, in the Realo wrapper app, we just open the original clicked url inside the app.

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
    // Get full url that the user originally clicked
    NSString *url = [userActivity.webpageURL absoluteString];

    // Navigate to the page inside our app
    [self.browserViewController openUrl: url];

    return YES;

That's it!

And that should be it! Normally you should now be able to use and handle incoming universal links in your app allowing you to do deep linking. A short demo video below of the implementation in the Realo wrapper app.

I started writing this article the week I implemented it, then I lost it somehow (??) and started all over again. So it's possible I might have missed something. If I did, please don't hesitate to ask questions. I'll be more than happy to update the article and help you out! Let me know if this has helped you and if it was clear, cheers ??!