Universal Links with Tapstream

Apple's Universal Links supersede custom URL schemes as the preferred method for linking into apps.

Universal Links Overview

To enable your app to use Universal Links with Tapstream, you'll need to complete the following steps, documented below:

  • Configure your Team and Bundle ID
  • (Optional) Configure your custom domains for use with Universal Links
  • Add the proper entitlements to your XCode project
  • Implement UL handling in your app using Tapstream's SDK
  • Ensure your project includes the SafariServices framework
  • Enable universal links on your campaigns

Configure your Team and Bundle IDs and enable Associated Domains

In order to associate itself with your app, Tapstream will need your Apple team identifier and your bundle id. You can retrieve these the Bundle Listing in Apple's Developer portal.

You'll also want to ensure that your app has the associated domains entitlement.

Once you've got your Team and Bundle ID, go into your Tapstream dashboard. Under the Account Configuration page, find the Apple Bundle Identifiers section and click "Add Bundle." Enter your Bundle and Team IDs here and click the Save Changes button.

Configure your custom domains

You can safely skip this section if you don't use custom domains or don't need them to work with Universal Links.

Universal Link Style

Tapstream allows you to choose between two different apple-app-site-association styles for each of your custom domains. Selecting either option is done via the Custom domains section of the Account Configuration page.

Namespaced

Namespaced is the default setting for new custom domains. It gives you the most flexibility at the expense of having a url prefix attached to your universal link enabled campaign click urls. This setting adds a /ul/* wildcard entry to your apple-app-site-association file and also an explicit path mapping for all of your UL enabled camapigns.

Benefits:

  • UL and non-UL campaigns can co-exist on the same domain.
  • Legacy campaigns will continue to work without changing any already-deployed campaigns.
  • New UL-enabled campaigns will work post app install.

Limitations:

  • Any campaigns you create on this domain after your initial UL rollout must include the /ul/ prefix on the click url if you want the campaign to work with existing installs.

Root Wildcard

Root wildcard adds a single root wildcard path to your apple-app-site-association file.

Benefits:

  • Legacy campaigns will work without modification.
  • Campaigns created post UL rollout do not require a click url prefix to work with existing installs.

Limitations:

  • All campaigns on this domain will always pop open the app regardless of the campaign being UL enabled or not.

Custom Domain SSL

To allow Universal Links to work on your custom domain you'll need to either provide Tapstream with an SSL certificate chain and private key which Tapstream will use to serve the apple-app-site-association file, or instruct Tapstream to provision a certificate and key on your behalf.

Automatic SSL Mode

Go to the Account Configuration page. Scroll down to the Custom domains section and select the "Automatic" option under "SSL Certificate Handling". Scroll down to the bottom of the page and click "Save Changes". Within a few minutes Tapstream will have provisioned a certifcate for your domain.

Manual SSL Mode

DO NOT give us your wildcard certificate and key. You should generate a new private key for this purpose.

When your custom domain's "SSL Certificate Handling" option is set to manual then your must provide a certificate and private key that matches your domain. Additionally the certificate and private key must satisfy Apple's App Transport Security requirements. The salient points are:

  • Key size must be at least 2048 bits.
  • Leaf certificate signing algorithm must be SHA-256 or greater.
  • Certificate chain must in a concatenated set of PEM encoded RSA certificates.
  • Private key must be a PEM encoded RSA key.

Once you have your key and full certificate chain, go to the Account Configuration page. Scroll down to the Custom domains section, select the "Manual" option under "SSL Certificate Handling" if it's not already selected and click on "Add Certificate". Paste in your certificate and key in the appropriate fields and click on "Upload Certificate." Scroll down to the bottom of the page and click "Save Changes". Campaign links on your custom domain should become accessible via https after a short delay.

Add the entitlement to your XCode Project

In your project, head to the Target settings. Under "Capabilities", find the "Associated Domains" entitlement and enable it. Add an entry: applinks:taps.io. If you have a custom domain, add a second entry with the domain, prepended by "applinks:".

Implement UL handling in your app

Universal Links are handled by adding an application:continueUserActivity:restorationHandler method to your AppDelegate. In this method, you'll need to pass the userActivity on to Tapstream's handleUniversalLink method. This is required for Tapstream to record the user visiting the link, since universal links override our usual redirectors.

handleUniversalLink accepts a callback, which will be passed a TSUniversalLinkApiResponse object (available from TSUniversalLinkApiResponse.h), which exposes 4 properties: deeplinkURL, fallbackURL, status, and error.

Status is a TSUniversalLinkStatus enum, which can have three values:

  • kTSULValid means that the link was recognized by Tapstream. At least one of the fallbackUrl or deeplinkUrl properties will be present.
  • kTSULDisabled means that the link is valid, but the campaign has disabled Universal Link support.
  • kTSULUnknown means that Tapstream did not recognize the link.

For most integrations, it is appropriate to simply check that the status is kTSULValid. If it is, you may parse the deeplinkURL and/or fallbackURL and display the relevant content accordingly. The deeplinkURL will contain a registered URL as defined by your campaign, while the fallbackURL will contain the fallback URL (i.e., the URL registered with a device type of "ANY").

Error handling

In the case of kTSULUnknown, you may want to check the error field. If the value is nil, it means the universal link is simply unknown to Tapstream and you should proceed accordingly.

Otherwise, error will be an NSError object, with one of the following codes (available from TSError.h):

  • kTSIOError: An error occurred communicating with Tapstream's server
  • kTSInvalidResponse: The server somehow returned some invalid JSON

In many applications, it will suffice to treat an error condition the same as any unknown link.

Example implementation

In case of an unhandled universal link, you should call openURL to redirect the user to Safari. An example of this usage:

func application(application: UIApplication,
                 willContinueUserActivityWithType userActivityType: String) -> Bool
{
    if(userActivity.activityType == NSUserActivityTypeBrowsingWeb)
    {
        return true
    }
    return false
}

func application(application: UIApplication,
                 continueUserActivity userActivity: NSUserActivity,
                 restorationHandler: ([AnyObject]?) -> Void) -> Bool
{
    if(userActivity.activityType == NSUserActivityTypeBrowsingWeb){

        TSTapstream.instance().handleUniversalLink(userActivity, completion: {
            (ul: TSUniversalLinkApiResponse?) -> Void in

            if(ul?.status == kTSULValid)
            {
                // Do deeplink things
                let deeplinkURL = ul?.deeplinkURL, fallbackURL = ul?.fallbackURL
                print("Universal Link Handled: \(deeplinkURL), \(fallbackURL)")
            }
            else if(ul?.status == kTSULDisabled)
            {
                // Direct the user back to the fallback URL using openURL
                UIApplication.shared.openURL((ul?.fallbackURL!)!);
            }
            else
            {
                // Fall back to the original URL if link was not handled.
                UIApplication.shared.openURL(userActivity.webpageURL!);
            }
        })

        return true;
    }
    return false;
}

Enable Universal Links on your campaigns

Universal Links can be enabled on a campaign-by-campaign basis. Just edit a campaign and make sure the "Universal Links" toggle is on.