- Resources
- Server configuration
- Client configuration
Here are some good URLs that might be of assistance:
- https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/AppSearch/UniversalLinks.html
- https://developer.apple.com/videos/play/wwdc2015-509/
- https://medium.com/@barsh/my-first-date-with-ios-universal-links-90dfabc88bb8
- https://developer.apple.com/documentation/safariservices/supporting_associated_domains_in_your_app
- https://search.developer.apple.com/appsearch-validation-tool/
- https://limitless-sierra-4673.herokuapp.com/
Follow these steps to setup Universal app linking on the web server. In this documentation we have examples for Apache2 and nginx but the same rules apply for IIS or any other webserver of your choice.
Below you'll find a template with a few examples:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "<TEAM_DEVELOPER_ID>.<BUNDLE_IDENTIFIER>",
"paths": [ "*" ]
},
{
"appID": "<TEAM_DEVELOPER_ID>.<BUNDLE_IDENTIFIER>",
"paths": [ "/articles/*" ]
},
{
"appID": "<TEAM_DEVELOPER_ID>.<ANOTHER_APP_BUNDLE_IDENTIFIER>",
"paths": ["/blog/*","/articles/*"]
}
]
}
}
PLEASE NOTE!
- The
"apps":
JSON key must be left as an empty array. - The
apple-app-site-association
JSON file must not have a.json
file extension.
This template gives you a lot more flexibility of how to handle certain URLs on your website. For instance you can specify a required URL query item with a particular name and a value of x numbers of characters. You can exlude URLs with #
that is common in AngularJS apps.
{
"applinks": {
"details": [
{
"appIDs": [ "ABCDE12345.com.example.app", "ABCDE12345.com.example.app2" ],
"components": [
{
"#": "no_universal_links",
"exclude": true,
"comment": "Matches any URL whose fragment equals no_universal_links and instructs the system not to open it as a universal link"
},
{
"/": "/buy/*",
"comment": "Matches any URL whose path starts with /buy/"
},
{
"/": "/help/website/*",
"exclude": true,
"comment": "Matches any URL whose path starts with /help/website/ and instructs the system not to open it as a universal link"
}
{
"/": "/help/*",
"?": { "articleNumber": "????" },
"comment": "Matches any URL whose path starts with /help/ and which has a query item with name 'articleNumber' and a value of exactly 4 characters"
}
]
}
]
},
"webcredentials": {
"apps": [ "ABCDE12345.com.example.app" ]
}
}
PLEASE NOTE!
- The
apple-app-site-association
JSON file must not have a.json
file extension.
OBS: Please note that as of iOS9 you no longer need to sign the apple-app-site-association
JSON file. However if you still need to support iOS8 or lower this is still required.
openssl smime -sign -nodetach
-in "unsigned.json"
-out "apple-app-site-association" -outform DER
-inkey /path/to/server.key
-signer /path/to/server.crt
- Upload the signed
apple-app-site-association
file to the server:
scp /path/to/apple-app-site-association [email protected]:~/
- Login to the web server:
ssh [email protected]
- Move the file to the root of the webserver (This might be another directory on your server)
mv apple-app-site-association /var/www/
The apple-app-association-file needs to be returned with the following Content-Type:
Minimum OS version | Content-Type |
---|---|
iOS9 or later | application/json |
iOS8 or lower | application/pkcs7-mime |
Below you'll find instructions on how to do this for your web server.
- Modify the
/etc/apache2/sites-available/default-ssl
(or equivalent) file to include the<Files>
snippet:
<Directory /path/to/root/directory/>
...
<Files apple-app-site-association>
Header set Content-type "application/json"
</Files>
</Directory>
- Modify the
/etc/nginx/sites-available/ssl.example.com
(or equivalent) file to include thelocation /apple-app-assocation
snippet:
server {
...
location /apple-app-site-association {
default_type application/json;
}
}
The JSON validation may fail if:
- The JSON file is invalid
- Redirects to something other than HTTPS
- From our experience any redirects will make Apples webscraper bot unable to parse the JSON file, you really should avoid them
- The server returns a 400-499 HTTP status code
- The server returns a 500-599 HTTP status code
- The Apples webscraper bot assumes that the file is temporarily unavailable and may retry again
For more information go to Apples documentation page Supporting Associated Domains in Your App and scroll down to the section "Validate the Apple App Site Association File".
- In Xcode go to
<MyApp>.xcodeproj/<Build target>/Capabilities
and turn on Associated domains.
2. Enter the domains you want the iOS app to respond to.
- This will generate a
<AppName>.entitlements
file that needs to be included in the project. - Please note that you need to enter subdomains specifically.
- If you already have a custom URI scheme i.e
myAppScheme://
, this method will already be implemented. - We have noticed that devices running iOS 9.0.x responds to this older method of handling app links.
- If you want to support iOS 9.0.x or earlier like iOS8/iOS7 you will need to implement this method and add a JavaScript iframe redirect to your website.
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
- Devices running iOS 9.1 or later supports Apple's Universal Links and to handle the incoming URL you need to implement the following methods:
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *))restorationHandler {
NSURL *url = userActivity.webpageURL;
// handle url
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
// handle url
}
Remember that when you make changes to either:
- The
<AppName>.entitlements
file in your iOS project - The
apple-app-site-association
JSON file
To delete the App from your testing device and compile it again. After an app has been successfully associated with a particular domain it will remain associated until the app is removed from the device.
When testing your deep links I recommend you to use either the iMessage app or the Notes app. If you use other 3rd party iOS applications such as Slack or Facebook Messenger the deeplinking might not work because that's dependent on how those 3rd party apps handle external URLs.
Does the file have to be signed, even if it's being forced over https?