With universal links, iOS can open specific links with relevant apps rather than a web browser. Since apps can provide a faster, more integrated user experience, they are often preferable for this purpose.
If your app is installed, and a user taps a universal link sent with Iterable, iOS opens the link in your app (which then tracks the link click using Iterable's iOS SDK or an API call). If your app is not installed, the link opens using a web browser (your link tracking domain tracks the click and redirects the user to the appropriate content on your website).
This document describes how to configure Iterable to send messages that include universal links.
In this article
Universal links overview
TIP
To learn how to configure which links Iterable rewrites as deep links, read Configuring Deep Links for Email or SMS.
An iOS app can indicate that it (rather than a web browser) should be used to open particular kinds of links.
To do this, its Xcode project should specify associated domains.
When installing or updating the app, iOS downloads
apple-app-site-association
files from these associated domains, examines
their contents, and uses any URL patterns associated with the app's App ID as an
indication of the links it can open. With this configuration in place, iOS
passes eligible links directly to the app in question, rather than to a web
browser.
For a deeper understanding of iOS universal links, read Apple's documentation:
- Universal Links for Developers
- Allowing Apps and Websites to Link to Your Content
- Supporing Universal Links in Your App
- Supporting Associated Domains
Universal links with Iterable
To help you understand if users are interacting with your content, Iterable
tracks link clicks. To do this, it rewrites URLs in your messages to point to
your tracking domain (a subdomain such as links.<YOUR_DOMAIN>.com
). This
domain is hosted by Iterable (as configured by your DNS), and captures click
information before redirecting users to the original link destination.
Iterable rewrites universal links, too. To decide how to do this, Iterable uses
your apple-app-site-association
files (you may have multiple—one per
relevant subdomain on your site).
At a high level, using universal links with Iterable works as follows:
You provide Iterable your
apple-app-site-association
files. These files indicate which links your app can open. For more details, read Configuring Deep Links for Email or SMS.Iterable hosts a combination of all of a single tracking domain's
apple-app-site-association
files athttps://<YOUR_LINK_TRACKING_DOMAIN>/apple-app-site-association
. For example,https://links.example.com/apple-app-site-association
.When you're setting up your iOS app, you add associated domains to its Xcode project. These associated domains link the app to your link tracking domain.
When a user installs or updates your app, iOS looks at its associated domains and downloads your link tracking domain's aggregate
apple-app-site-association
file.When you're sending a campaign, Iterable inspects each link in the message and compares it to the paths in the tracking domain's aggregate
apple-app-site-association
file, looking for a match. If a match is found, Iterable rewrites the link as a deep link.-
When a user receives your message on an iOS device and taps on the rewritten link:
If your app is installed, iOS uses it to open your link. In your app, Iterable's SDK (or an API call) tracks information about the link click.
Otherwise, iOS opens the link in a web browser, where your link tracking domain captures information about the click before redirecting the user to the content.
Instructions
To support Universal Links in your iOS app, follow these steps:
-
If you haven't already done so, configure your DNS records to support your tracking domain. For more information, read Email Setup.
NOTE
After Iterable rewrites links, they have following URL formats:
- Normal links:
links.<YOUR_DOMAIN>.com/u/<PATH>
- Deep links:
links.<YOUR_DOMAIN>.com/a/<PATH>
Normal links contain
/u/
, and deep links contain/a/
. - Normal links:
-
Set up HTTPS for your Iterable link tracking domain.
For Iterable to successfully rewrite deep links and have your app open them as expected, it must host an
apple-app-site-association
file at your link tracking domain.Since iOS requires that you host
apple-app-site-association
files with HTTPS (and without redirects), you must set up HTTPS for your link tracking domain. To do this, follow the instructions in Setting up Link Tracking Domains to use HTTPS. -
Find your
apple-app-site-association
files or create them for each subdomain, as needed.NOTES
- For more information about the
apple-app-site-association
file and how to create one, read Apple's Supporting Associated Domains document. - Iterable can now use unmodified
apple-app-site-association
files to understand how to rewrite links for deep linking. Previously, we required a custom"appID": "iterable"
section in this file; this is no longer necessary, but we still support this older format. - If you'd like to update your
apple-app-site-association
file to use the the standard format, contact Iterable Support. See Working with Iterable Support.
If your iOS app currently works with Universal Links, your website already hosts an
apple-app-site-association
file. Apple's Support Universal Links document specifies the following:After you create the apple-app-site-association file, upload it to the root of your HTTPS web server or to the .well-known subdirectory. The file needs to be accessible via HTTPS—without any redirects—at
https://<domain>/apple-app-site-association
orhttps://<domain>/.well-known/apple-app-site-association
To create an
apple-app-site-association
file, use a format similar to the following:{ "applinks": { "apps": [], "details": [ { "appID": "<TEAM_ID>.<BUNDLE_ID>", "paths": [ "NOT /samplepath/toignore", "/samplepath/*" ] } ] } }
The
paths
section defines rules that define which URLs your app can handle. For example:-
NOT /samplepath/toignore
defines a URL your app cannot open. When sending messages, Iterable rewrites links that match this path as normal links (containing/u/
). -
/samplepath/*
defines a set of URLs your app can open. When sending messages, Iterable rewrites links that match this path as universal links (containing/a/
).
- For more information about the
Provide the
apple-app-site-association
files to Iterable, as described in Configuring Deep Links for Email or SMS.-
Configure your Xcode project's Associated Domains.
To understand which links to open with your app instead of a web browser, iOS examines the app's
apple-app-site-association
files. To determine how to download these files, iOS looks at the associated domains declared in the app's Xcode project.Iterable hosts an aggregate
apple-app-site-association
file at your link tracking domain. In your Xcode project's Signing & Capabilities tab, add the link tracking domain to the list of Associated Domains. Use anapplinks:
prefix.For example, assuming your link tracking domain is
links.<YOUR_DOMAIN>.com
:NOTE
iOS downloads a fresh copy of an app's
apple-app-site-association
file only when installing or updating that app. Because of this, changes to this file should be accompanied by a new version of the app. -
Update your app's code to handle Universal Links.
If you're using Iterable's iOS SDK, update your app delegate's
application(_:continue:restorationHandler:)
method to get the deep link URL and pass it toIterableAPI.handle(universalLink:)
:Swift
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool { guard let url = userActivity.webpageURL else { return false } // This tracks the click, retrieves the original URL, and uses it to // call handleIterableURL:context: return IterableAPI.handle(universalLink: url) }
Objective-C:
- (BOOL)application:(UIApplication *)application continueUserActivity(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler { // This track the click, retrieves the original URL, uses it to call // `handleIterableURL:context:` return [IterableAPI handleUniversalLink:userActivity.webpageURL]; }
If you aren't using Iterable's iOS SDK, use code similar to the snippet found on Deep Links Without the SDK for your app delegate's
application:continueUserActivity:restorationHandler
method. -
Navigate to a specific view or screen in your application.
TIP
This step is relevant only if you're using Iterable's iOS SDK.
Deep links usually navigate the user to a specific place in your app, to view some particular piece of content or information.
You can place this navigation logic in the
IterableURLDelegate.handle(url:)
method, which is called after Iterable tracks the link click and grabs any campaign-related information from it. In itsurl
parameter, this method receives the original link you placed in your message content, and your app can inspect it as necessary and decide where to take the user.Below,
IterableURLDelegate.handle(url:)
calls out toDeepLinkHandler
, a custom method that handles the navigation. If you follow this pattern, you'll need to provide your own implementation for this method. For a reference implementation of this method, check out our sample code.Swift:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // ... // Initialize Iterable SDK let config = IterableConfig() // ... config.urlDelegate = self IterableAPI.initialize(apiKey: "<YOUR-API-KEY>", launchOptions: launchOptions, config: config) } // Iterable URL delegate. It will be called when you receive // an `openUrl` event from push notification. func handle(iterableURL url: URL, inContext context: IterableActionContext) -> Bool { return DeeplinkHandler.handle(url: url) }
Objective-C:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // ... // Initialize Iterable SDK IterableConfig *config = [IterableConfig new]; // ... config.urlDelegate = self; [IterableAPI initializeWithApiKey:@"<YOUR-API-KEY>" launchOptions:launchOptions config:config]; } // Iterable URL delegate. It will be called when you receive // an `openUrl` event from push notification. - (BOOL)handleIterableURL:(NSURL *)url context:(IterableActionContext *)context { return [DeeplinkHandler handleUrl:url]; }
-
Make sure your website can display all necessary content
Some of your users probably won't have your iOS app installed; when these users click Universal Links, they will be directed to your website rather than your app. It's important to make sure that your website can display the necessary content for all links included in your messages.