Deep linking with Yozio Mobile Growth API on iOS

Overview

The Deep Link of Yozio SuperLinks covers users who already have your app and click on a Yozio SuperLink. There are a number of ways you can handle the users who already have your app, and the deep link case can be divided into three core pieces of functionality to help you achieve your use case:

  • Opening your app
  • Data passing
  • Tracking

Opening your app on iOS

If you’d like to implement more complex user flows for those users who deep link into your app, you must first implement a seamless experience for your users to open your app through a Yozio SuperLink. In order for your app to open when a user clicks on a Yozio SuperLink, your app must first be configured to recognize the SuperLink.

For your users on iOS 9+, we have two options to deep link your users, via custom scheme and via Universal Links. For iOS 9+ users Apple’s Universal Links will provide the superior user experience, but there are various edge cases that make Apple’s Universal Links difficult to implement. We’ve provided a complete solution in our support for Universal Links that will allow you to handle this edge cases and control the user experience.

Setup

First, implement a custom scheme for your app. Check out Apple’s documentation for more information on how to implement Custom Scheme.

Then, for individual SuperLinks, go to Yozio Console > SuperLinks > Organic Links > Edit (the SuperLink you’d like to modify) > Redirect Settings > iOS > Do you want to override default settings? > Yes > Deep Link User? > Yes > then enter your custom scheme

For all SuperLinks, go to Yozio Console > Settings > Default Redirect Settings > iOS > Deep Link User? > Yes > then enter your custom scheme

Make sure to enter your custom scheme in the iOS Custom Scheme field.

Notes

If you choose to implement deep linking using custom scheme, there are a few important user experience pieces to be aware about:

Yozio uses a fallback solution to deep link users into the app; this is due to the lack of any way to detect whether or not a user has the app without Universal Link (a design choice that Apple has explicitly made and that Yozio cannot influence). Yozio will first attempt to open the app using the custom scheme you provide. If the user does not have the app, an attempt to open a custom scheme that is not recognized by any app on the phone causes a "cannot open in safari" popup to appear. After this popup, we will redirect the user to the app store. Additionally, users on iOS 9 will see a “open in YOUR_APP_NAME” popup appear when the user opens your app through a custom scheme.

We recommend implementing Yozio’s support for Universal Links to ensure your iOS 9+ users have the best experience.

Check out this article for information on how to integrate Yozio’s support for Universal Links. Skip any steps regarding the SDK (the first step regarding integrating the Yozio SDK, and the step regarding the restorationHandler). Additionally, check out the section "Data Passing Over Deep Links" for information on passing metadata into your app.

Once inside the app, you’ll want your app to parse the data from the corresponding click event. Since the click event results in the app opening directly, all data appended to the SuperLink URL is preserved and passed into the app; all that is required is that the metadata is parsed into something that the app can easily access. Additionally, this is where the app opening is confirmed to have come from a click on a Yozio SuperLink; clicks on Yozio SuperLinks carry a piece of metadata indicating that the app was opened through a SuperLink, and not through other means.

On iOS, there are two possible avenues into your app that a user can take, custom scheme and Universal Link. For the best possible user experience, make sure that you are parsing the metadata from both avenues.

Retrieving metadata from the custom scheme URL

When an app is opened via custom scheme from another app (such as safari, SMS, or email), the app delegate function openURL is called. A parameter is passed to this function, url, which contains the full URL that opened the app. Any and all metadata will be found in the query string portion of the URL. In openURL, parse the metadata into an array or dictionary for use later in the app. Here is how our SDK accomplishes this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(NSDictionary<NSString *, id> *)options
{   
    NSDictionary *metaData = [Utils parseQueryString:[url query]];
    NSLog(@"Got meta data from deep link :%@", metaData);
}

+ (NSDictionary *)parseQueryString:(NSString *) queryString
{
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    NSArray *pairs = [queryString componentsSeparatedByString:@"&"];

    for (NSString *pair in pairs){
        NSArray *elements = [pair componentsSeparatedByString: @"="];
        // replace + with blank string in query string, e.g: a=b+c => a=b c

        NSString *key = [[elements objectAtIndex:0] stringByReplacingOccurrencesOfString:@"+" withString:@" "];

        // replace html encoded with percent escapes, e.g: a=b%2Bc => a=b+c
        key = [key stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

        // handle case like a=b&d, prevent from crash
        if ([key length] == 0) {
            continue;
        }

        NSString *value;

        if ([elements count] > 1) {
            value = [[elements subarrayWithRange: NSMakeRange(1, [elements count] - 1)]componentsJoinedByString:@"="];
            value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "];
            value = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        } else {
            value = @"";
        }
        [dict setObject:value forKey:key];
    }
    return dict;
}

Dynamically attached metadata on Universal Links can be retrieved in a similar fashion to metadata on custom schemes. Instead of openURL however, when a user deep links into your app via Universal Links, the appDelegate function continueUserActivity will be called. Specifically, to distinguish that a user came from a Universal Link, the user activity type will be NSUserActivityTypeBrowsingWeb, and the NSUserActivity passed to the function continueUserActivity will contain the URL and query string:

1
2
[userActivity.webpageURL query]
[NSUserActivityTypeBrowsingWeb]

Here is some sample code (in the AppDelegate) demonstrating all the parts in action:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
 restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler
{
    if ([NSUserActivityTypeBrowsingWeb isEqualToString: userActivity.activityType]){

        NSDictionary *metaData = [Utils parseQueryString:[url query]];

        if ([metaData objectForKey:@"__y"] != nil) {
            //this means the that the app has been opened by a SuperLink

            NSString SHORT_URL = [metaData objectForKey:@"__ysurl"];

            List<YozioNameValuePair> getParams = new LinkedList<YozioNameValuePair>();
            getParams.add(new YozioNameValuePair("method", "link.get"));
            getParams.add(new YozioNameValuePair("app_key", APP_KEY));
            getParams.add(new YozioNameValuePair("short_url", SHORT_URL));

            String response = doGetRequest(YOZIO_API_BASE_URL, getParams);
        }
    }
}

If you are using Yozio’s support for Universal Link, you will need to take extra measures in order to pass statically attached metadata into your app. Since Universal Link deep links into your app at the operating system level, the user will be deep linked before Yozio has the opportunity to attach static metadata to the SuperLink. You’ll notice in the sample code above a call to the link.get API. This will enable you to retrieve the static metadata associated with the Yozio SuperLink. Simply parse the metadata out of the response of the API request. Check out this article for more details on using the SuperLink Get API.