I'm a software developer based in the UK. I am blogging regularly about software development & Apple

Universal Links with iOS 9

I managed these days to get Universal Links working for me. Universal Links are a new feature in iOS 9 and a replacement for the old scheme model e.g. youtube://<link>.  To get it working did cost me more time than I initially expected. Because of this, the questions I had on my journey and all the problems I read about from other developers on the internet, I decided to dedicate this issue of my blog to Universal Links.


Setting up Universal Links is actually quite easy. Just follow these 4 easy steps:

  1. Make sure your server certificate is valid.
  2. Upload the apple-app-site-association to your web-servers root or .well-known - folder and set its mime-type to application/json (see below for a sample configuration).
  3. Update or add associated domains entitlement via Xcode to your provisioning profile and add your domains (see Picture 1). Don't forget to prefix your domains with applinks: e.g. applinks:www.google.com
  4. Add delegate callback (application:continueUserActivity:restorationHandler:) to your appdelegate.
Picture 1 - Associated Domains Section in Xcode - Capabilities - tab

Picture 1 - Associated Domains Section in Xcode - Capabilities - tab

Easy, right? Well, as I said, it wasn't that easy for me. Having had a wrong team-id for the apple-app-site-association made file me wonder what was going on. Tutorials on the internet tell you that you need to use the Team ID given here. While this is indeed a Team ID, it's not necessarily the one you need. The ID that matters is in the section Certificates, IDs & Profiles listed with your bundle ID here.

Picture 2 - Team ID to use for apple-app-site-association file

Picture 2 - Team ID to use for apple-app-site-association file

My understanding is that both IDs are initially the same, but don't have to be when more and more teams start using the same account to create app IDs for their projects. So if you have an Apple individual developer account, they are probably the same but if you are using an Apple company account which already exists for years, there's a high chance they are different.

Debugging Universal Links

While I didn't know why Universal Links weren't working for me, I questioned everything and had all kinds of ideas. So if you are still figuring out what is wrong with your setup, let me help you by answering all those questions I came up with during my debugging efforts.

  • Universal Links cannot be tested in Simulator. They must be tested on a device
  • The apple-app-site-association file does definitely NOT have to be signed
  • Universal Links can be tested with iMessage, Apple's Mail App and even Notes.
  • Universal Links work in private networks in contrast to their Android counterpart
  • They can be tested directly via Xcode. No need to push your build to Testflight. Just set a breakpoint in the delegate callback and trigger a link in iMessage
  • When adding domains to your entitlements, www.domain.com is different from domain.com. You have to add both e.g. applinks:wwww.domain.com, applinks:domain.com
  • The apple-app-site association file can be validated via Apple's API Validation tool. But mind that your server needs to be reachable from outside.
  • The apple-app-site-association file will be cached on the device. Make sure it uses the latest version.

My recommendation is to start out with a generic version (in regards to paths key) and take it from there. Below you can find a working apple-app-site-association file. Just add your team & bundle ID. (Mind path is ["*","/"] instead of just ["*"]:

    "applinks": {
        "apps": [],
        "details": [
                "appID": "<team id>.<your bundle id>",
                "paths": ["*","/"]

By the way, it never hurts to check how configuration files from other companies look like e.g. Google, LinkedIn, Youtube & Netflix.


A few links I found useful on my debugging journey:

Migrating to Swift 3 & iOS 10

WWDC 2016. What's new?