Integrate Blueshift's deep links

This article provides steps on how to use Blueshift's deep links (commonly known as universal links) to launch pages in your iOS app.

📘

Wait. Are you ready for this part?

In this article, we'll show you how to integrate Blueshift's deep links with your app. However, this cannot work until you have the SDK in your Xcode project and you can use it in your app. If not, then we suggest that you do those things first and then come back here.

It's absolutely not complicated. And, if you've come this far, you know that this works. :relaxed:

You can use Blueshift's deep links in the campaigns that you run with us. Blueshift's deep links are usual https URLs that take users to a page in the app if they click on one of them or launch them in a browser. If an email or text message that we send as a part of your campaign contains a Blueshift deep link and a user clicks on it, iOS can launch the app and take the user to the page that is mapped to it.

Prerequisites

Before you get started, there are a couple of things that we need you to do:

  • The Blueshift deep link domain should have a cname record that points to links.getblueshift.com. This is probably done if you have configured email campaigns with us. A valid cname record looks like links.clientdomain.com that points to links.getblueshift.com. Only top-level domains and subdomains are supported at the moment. For example, either clientdomain.com or links.clientdomain.com should point to links.getblueshift.com. We do not support path on a domain such as links.clientdomain.com/repo/folder.
    Reach us on [email protected] if it's not done yet and you want to set it up.
  • Share the Apple App Site Association file with us. Perform the following steps to submit the AASA file on our platform.
    1. Sign in to the Blueshift web app.
    2. On the Account Settings page, select the Other Settings tab.
      alt text
    3. Provide the following details Blueshift account executive on this page:
FieldDescription
AASA File Copy-paste the contents of the Apple-App-Site-Association (AASA) file to use the deep links functionality of our SDK.
Asset Links FileCopy-paste the contents of the applinks.json file if you have an Android app and you want to use the Blueshift deep links functionality of our SDK. For more information on our Android SDK, see About Blueshift's Android SDK.

For more information on this, see Enabling universal links.
Here's an example of the Apple App Site Association (AASA) File:

{
    "applinks": {
        "apps": [],
        "details": [{
            "appID": "<Team_id>.<Bundle ID>",
            "paths": ["/z/*","/track"]
            }]
    }
}

The AASA file is basically a JSON where app ID is the identifier of the application that will handle the Blueshift's deep links and paths are the sections which need to be supported by the app.

Paths in the file can specify if iOS should launch the links in the app or in the browser. Blueshift uses the paths /z/* and /track for rewriting the email links. Add these paths to the AASA file to let Blueshift links go to the app. Refer to this document to know more on setting up the email links.

Integration

Before you start configuring the SDK, ensure that

  • Associated Domains capability is enabled for your app
  • Add your domains to the associated domains capability of your Xcode project

Perform the following steps to do this:

  1. If the Associated Domains capability is not enabled for your app:
    1. Sign in to the Apple Developer Portal, and click on Certificates, Identifiers & Profiles.
    2. On the left navigation panel, choose Identifiers.
    3. Choose your app's identifier on the right-panel under Identfiers.
    4. Enable Associated Domains under Capabilities and click Save.
  2. Now, select your app's project in Xcode's project browser.
  3. Select the right target under the TARGETS and select the Signing & Capabilities tab. If Associated Domains capability is not present under this tab, click + Capability and double click on Associated Domains in the list to add this capability to the target.
  4. Now, click + under the Associated Domains capability to add a new entry. Add the entry as:
    • applinks:<domain name>
      For example, applinks:universallinks.blueshiftreads.com
1304

For example, if links.clientdomain.com is the domain that you have created to handle Blueshift's deep links, provide it here. This is also the domain that is mapped to links.getblueshift.com.

Implement BlueshiftUniversalLinksDelegate

Now, set the BlueshiftUniversalLinksDelegate in the AppDelegate.m or AppDelegate.swift file:

//Set blueshiftUniversalLinks delegate
config.blueshiftUniversalLinksDelegate = self
//Set blueshiftUniversalLinks delegate
[config setBlueshiftUniversalLinksDelegate:self];

The BlueshiftUniversalLinksDelegate has 3 methods:

  • The didStartLinkProcessing method receives a callback that states that the SDK has started processing the Blueshift deep link. You can use this method to show the activity indicator on screen.
  • The didCompleteLinkProcessing(_ url: URL?) method receives the callback if the SDK processes the Blueshift deep link successfully.
  • The didFailLinkProcessingWithError(_ error: Error?, url: URL?) method receives the callback if the SDK fails to process the Blueshift deep link.
extension AppDelegate: BlueshiftUniversalLinksDelegate {
    
    //callback to indicate the start of processing of url
    func didStartLinkProcessing() {
        //show activity indicator
    }
    
    //Universal link will be received here on successful processing
    func didCompleteLinkProcessing(_ url: URL?) {
        //handle success by navigating to the respective screen and hide activity indicator
    }
    
    //Error will be received here with unprocessed url on unsuccessful processing
    func didFailLinkProcessingWithError(_ error: Error?, url: URL?) {
        //Handle failure and hide activity indicator
    }
}
@interface AppDelegate : UIResponder <UIApplicationDelegate,  BlueshiftUniversalLinksDelegate>
@property (strong, nonatomic) UIWindow *window;

@end

  
@implementation AppDelegate

//callback to indicate the start of processing of url
-(void)didStartLinkProcessing {
    //show activity indicator
}
 
//Universal link will be received here on successful processing
-(void)didCompleteLinkProcessing:(NSURL *)url {
    //handle success by navigating to the respective screen and hide activity indicator
}
 
//Error will be received here with unprocessed url on unsuccessful processing
-(void)didFailLinkProcessingWithError:(NSError *)error url:(NSURL *)url {
    //Handle failure and hide activity indicator
}
@end

Configure continueUserActivity method

Pass the URL/activity from the continueUserActivity method to the SDK so that the SDK can process the URL and perform attribution. After processing the URL, the SDK sends the URL in the BlueshiftUniversalLinksDelegate methods for apps that the SceneDegate enabled as well as apps that have it disabled.

Non-SceneDegate Apps
Add [BlueShift sharedInstance].appDelegate handleBlueshiftUniversalLinksForActivity: userActivity] call to the SDK inside application: continueUserActivity: delegate method of the AppDelegate.m or AppDelegate.swift file.

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
		BlueShift.sharedInstance()?.appDelegate?.handleBlueshiftUniversalLinks(for: userActivity)
		 return true
}
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity
 restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *restorableObjects))restorationHandler {
    [[BlueShift sharedInstance].appDelegate handleBlueshiftUniversalLinksForActivity: userActivity];
    return YES;
}

SceneDelegate enabled Apps
SDK v2.1.12 onwards, add the following code in the SceneDelegate class's willConnectTo:Session: and continueUserActivity methods. iOS will deliver the universal link URL in the willConnectTo:Session method if the app is in the killed state. If the app is in the background state, the URL will be delivered to the continueUserActivity method.

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        
        guard let _ = (scene as? UIWindowScene) else { return }

        if let activity = connectionOptions.userActivities.first, let url = activity.webpageURL, BlueShift.sharedInstance()?.isBlueshiftUniversalLinkURL(url) == true {
            blueshiftAppDelegate?.handleBlueshiftUniversalLinks(for: activity)
        }
    }



    func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
     // Check the url and pass to SDK 
        if let url = userActivity.webpageURL, BlueShift.sharedInstance()?.isBlueshiftUniversalLinkURL(url) == true {
            BlueShift.sharedInstance()?.appDelegate?.handleBlueshiftUniversalLinks(for: userActivity)
        }
    }
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions  API_AVAILABLE(ios(13.0)){
    if ([[[connectionOptions userActivities] allObjects]firstObject] != nil) {
          [[BlueShift sharedInstance].appDelegate handleBlueshiftUniversalLinksForActivity:[[[connectionOptions userActivities] allObjects]firstObject]];
      }
}

- (void)scene:(UIScene *)scene continueUserActivity:(NSUserActivity *)userActivity API_AVAILABLE(ios(13.0)) {
        [[BlueShift sharedInstance].appDelegate handleBlueshiftUniversalLinksForActivity: userActivity];
}

❗️

Ensure that you replace links.clientdomain.com with the cname-record value that points to links.getblueshift.com.

For information on how to integrate Blueshift's deep links for Android (called Android app links), see Integrate Blueshift deep links on Android.

Troubleshooting

App is not launched if a Blueshift deep link is clicked.

  • Ensure that the user is not pasting the links in the browser. The best way to test the Blueshift's deep links is to open it from an email. You can send a test email with Blueshift's deep links by creating the templates and test campaigns.
  • Ensure that you have your AASA file hosted and it's correct. To check the hosted AASA file, go to
    https://<<yourdomain>>/.well-known/apple-app-site-association.
    For example, https://universallinks.blueshiftreads.com/.well-known/apple-app-site-association.
  • Ensure that you have Associated Domain capability enabled in the XCode project setting, and it has an entry of applinks with your universal links domain.
    For example, applinks:universallinks.blueshift.com.

How to handle the existing Universal Links or Universal Links that do not come from a Blueshift campaign?
Use the helper function isBlueshiftUniversalLinkURL: to identify if the URL is from Blueshift. If it returns true, call handleBlueshiftUniversalLinks(for:url) function and handle the existing universal links or universal links other than Blueshift deep links using an if-else statement. For example:

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
        if let url = userActivity.webpageURL {
            if BlueShift.sharedInstance()?.isBlueshiftUniversalLinkURL(url) == true {
                BlueShift.sharedInstance()?.appDelegate?.handleBlueshiftUniversalLinks(for: url)
            } else {
                // handle existing Universal links or Universal Links other than Blueshift
            }
        }
        return true
    }
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity
 restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *restorableObjects))restorationHandler {
    NSURL *url = userActivity.webpageURL;
    if (url != nil) {
        if ([[BlueShift sharedInstance] isBlueshiftUniversalLinkURL:url]) {
            [[BlueShift sharedInstance].appDelegate handleBlueshiftUniversalLinksForURL:url];
        } else {
            	// handle existing Universal links or Universal Links other than Blueshift 
        }
    }
    return YES;
}

I want a user to launch few URLs in the app, and few in the browser. How do I do that?
In the AASA file, you can specify whether iOS should launch a URL in the app or in the browser. For more information, see this document.
Blueshift uses paths /z/* and /track for email rewriting which can be used to filter the paths. Refer to this document for more.

How to support multiple apps using the same universal link domain?
Add your AppID in the AASA file. For more information, see this document.

How to support multiple universal link domains in the same app?
Add your domains to the associated domains capability of your Xcode project. For example:

  • applinks:universallinks.blueshift.com
  • applinks:links.blueshift.com