{"_id":"5af117a422d66500034614cf","project":"55e67aaa9cc7c62b00c4a1ea","version":{"_id":"55e67aab9cc7c62b00c4a1ed","project":"55e67aaa9cc7c62b00c4a1ea","__v":12,"createdAt":"2015-09-02T04:27:23.612Z","releaseDate":"2015-09-02T04:27:23.612Z","categories":["55e67aac9cc7c62b00c4a1ee","55e67b5556007d23005fee7d","55e67b5dde6fef23009480ca","55e680efde6fef23009480db","55e6829485a9741900314e99","561c61b4ad272c0d00a892df","586c014c0abf1d0f000d04d4","58991d2ad207df0f0002186b","589b8e1fdbb7cd190026732c","58b8ca5e3265d70f001788d4","5af0fe494ca2730003cbc98a","5af0fe55ec80af0003804ca2"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.2.0","version":"1.2"},"category":{"_id":"589b8e1fdbb7cd190026732c","project":"55e67aaa9cc7c62b00c4a1ea","__v":0,"version":"55e67aab9cc7c62b00c4a1ed","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2017-02-08T21:31:11.878Z","from_sync":false,"order":7,"slug":"advanced-techniques","title":"Advanced Techniques"},"user":"587fed3d9efedf3b00200366","__v":0,"parentDoc":null,"updates":[],"next":{"pages":[],"description":""},"createdAt":"2018-05-08T03:21:08.127Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":18,"body":"When email is sent from Sailthru Email Manager, we go through the links in the templates, and then replace them with redirects, with domains of your choosing, generally something in the form of `http://link.yourdomain.com`. This allows us to track tap-through metrics on emails and measure your success. For example. Sailthru maintains a fake online clothing store, Varick and Vandam, as a demonstrator platform. Links in emails from V+V will look something like this: `http://link.varickandvandam.com/click/13071627.1/aHR0cHM.....`\n\nbut will redirect to: https://varickandvandam.com/products/1085431\n\n\nIn combination with Universal Links, the Carnival SDK can be configured to handle these links and to open your app whenever a certain type of link is clicked.\n\nMake sure you've followed the steps in the [Sailthru Docs](https://getstarted.sailthru.com/account/management/apple-ios-app-universal-links/) before starting this guide - it corresponds to the \"Link Parsing and Tracking\" section.\n\n# Handling Universal Links From a Sailthru Email\nTo properly handle Universal Links, your app will need to implement the `UIApplicationDelegate:application:continueUserActivity:restorationHandler:` method in its `AppDelegate`. When an app is opened with a Universal Link, this method is called with an instance of `NSUserActivity`, which will have a the URL the user clicked on as its `webpageURL` property. With this knowledge in mind, we can implement this method:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: :::at:::escaping ([Any]?) -> Void) -> Bool {\\n    let routingURL;\\n    if let incomingURL = userActivity.webpageURL {\\n        if incomingURL.host! == \\\"link.yourdomain.com\\\" { // It's a Sailthru link, so we'll have to decode it\\n            routingURL = Carnival.handleSailthruLink(incomingURL)\\n        } else { // We can handle this one without calling Carnival\\n            routingURL = incomingURL\\n        }\\n\\n        routeToViewForURL(incomingURL) // Go to the correct view in the app for the content tapped on\\n        return true\\n    }\\n    return false;\\n}\",\n      \"language\": \"swift\",\n      \"name\": \"AppDelegate.swift\"\n    },\n    {\n      \"code\": \"- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {\\n    NSURL *routingURL;\\n    if ([continueUserActivity webpageURL] != nil) {\\n        NSURL *incomingURL = [continueUserActivity webpageURL];\\n        if ([[incomingURL host] isEqualToString:@\\\"link.yourdomain.com\\\"]) {\\n            routingURL = [Carnival handleSailthruLink:incomingURL];\\n        } else {\\n            routingURL = incomingURL;\\n        }\\n        [self routeToViewForURL:routingURL];\\n        return true;\\n    }\\n    return false;\\n}\",\n      \"language\": \"objectivec\",\n      \"name\": \"AppDelegate.m\"\n    }\n  ]\n}\n[/block]\nNote that the method `routeToViewForURL` is just a placeholder, as different apps will have different ways of parsing web URLs into App views.\n\nCalling this `Carnival:handleSailthruLink` method does two things:\n1. Takes the encoded `link.yourdomain.com/click/...` link and returns its redirect destination - the link that was entered into the template on Sailthru.\n2. Pings the link domain using `NSURLConnection`, meaning that tapthrough analytics will be preserved on the Sailthru platform.\n\n# Caveat\nAt this time, links from Sailthru come in HTTP scheme by default, and internally, the Carnival SDK uses `NSURLSession` to query them when pinging the `link.yourdomain.com/click/...` link. Unfortunately, this means that for the time being, you'll have to add an ATS exception for your domain. You can do this in your `Info.plist` file as below:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/d96e3b7-Screen_Shot_2018-05-08_at_4.04.00_PM.png\",\n        \"Screen Shot 2018-05-08 at 4.04.00 PM.png\",\n        882,\n        152,\n        \"#dcdcda\"\n      ],\n      \"caption\": \"The K/V Structure in the Info.plist defining ATS Exception behaviour\"\n    }\n  ]\n}\n[/block]\nOr, in XML form:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"<!-- At the top level of the Info.plist file  -->\\n<key>NSAppTransportSecurity</key>\\n<dict>\\n  <key>NSExceptionDomains</key>\\n  <dict>\\n    <key>link.yourdomain.com</key>\\n    <dict>\\n      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>\\n      <true/>\\n    </dict>\\n  </dict>\\n</dict>\",\n      \"language\": \"xml\",\n      \"name\": \"Info.plist\"\n    }\n  ]\n}\n[/block]\nWe're looking to have Sailthru links using HTTPS by default as soon as possible.","excerpt":"","slug":"ios-handling-sailthru-links","type":"basic","title":"iOS: Handling Universal Links from a Sailthru Email"}

iOS: Handling Universal Links from a Sailthru Email


When email is sent from Sailthru Email Manager, we go through the links in the templates, and then replace them with redirects, with domains of your choosing, generally something in the form of `http://link.yourdomain.com`. This allows us to track tap-through metrics on emails and measure your success. For example. Sailthru maintains a fake online clothing store, Varick and Vandam, as a demonstrator platform. Links in emails from V+V will look something like this: `http://link.varickandvandam.com/click/13071627.1/aHR0cHM.....` but will redirect to: https://varickandvandam.com/products/1085431 In combination with Universal Links, the Carnival SDK can be configured to handle these links and to open your app whenever a certain type of link is clicked. Make sure you've followed the steps in the [Sailthru Docs](https://getstarted.sailthru.com/account/management/apple-ios-app-universal-links/) before starting this guide - it corresponds to the "Link Parsing and Tracking" section. # Handling Universal Links From a Sailthru Email To properly handle Universal Links, your app will need to implement the `UIApplicationDelegate:application:continueUserActivity:restorationHandler:` method in its `AppDelegate`. When an app is opened with a Universal Link, this method is called with an instance of `NSUserActivity`, which will have a the URL the user clicked on as its `webpageURL` property. With this knowledge in mind, we can implement this method: [block:code] { "codes": [ { "code": "func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool {\n let routingURL;\n if let incomingURL = userActivity.webpageURL {\n if incomingURL.host! == \"link.yourdomain.com\" { // It's a Sailthru link, so we'll have to decode it\n routingURL = Carnival.handleSailthruLink(incomingURL)\n } else { // We can handle this one without calling Carnival\n routingURL = incomingURL\n }\n\n routeToViewForURL(incomingURL) // Go to the correct view in the app for the content tapped on\n return true\n }\n return false;\n}", "language": "swift", "name": "AppDelegate.swift" }, { "code": "- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {\n NSURL *routingURL;\n if ([continueUserActivity webpageURL] != nil) {\n NSURL *incomingURL = [continueUserActivity webpageURL];\n if ([[incomingURL host] isEqualToString:@\"link.yourdomain.com\"]) {\n routingURL = [Carnival handleSailthruLink:incomingURL];\n } else {\n routingURL = incomingURL;\n }\n [self routeToViewForURL:routingURL];\n return true;\n }\n return false;\n}", "language": "objectivec", "name": "AppDelegate.m" } ] } [/block] Note that the method `routeToViewForURL` is just a placeholder, as different apps will have different ways of parsing web URLs into App views. Calling this `Carnival:handleSailthruLink` method does two things: 1. Takes the encoded `link.yourdomain.com/click/...` link and returns its redirect destination - the link that was entered into the template on Sailthru. 2. Pings the link domain using `NSURLConnection`, meaning that tapthrough analytics will be preserved on the Sailthru platform. # Caveat At this time, links from Sailthru come in HTTP scheme by default, and internally, the Carnival SDK uses `NSURLSession` to query them when pinging the `link.yourdomain.com/click/...` link. Unfortunately, this means that for the time being, you'll have to add an ATS exception for your domain. You can do this in your `Info.plist` file as below: [block:image] { "images": [ { "image": [ "https://files.readme.io/d96e3b7-Screen_Shot_2018-05-08_at_4.04.00_PM.png", "Screen Shot 2018-05-08 at 4.04.00 PM.png", 882, 152, "#dcdcda" ], "caption": "The K/V Structure in the Info.plist defining ATS Exception behaviour" } ] } [/block] Or, in XML form: [block:code] { "codes": [ { "code": "<!-- At the top level of the Info.plist file -->\n<key>NSAppTransportSecurity</key>\n<dict>\n <key>NSExceptionDomains</key>\n <dict>\n <key>link.yourdomain.com</key>\n <dict>\n <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>\n <true/>\n </dict>\n </dict>\n</dict>", "language": "xml", "name": "Info.plist" } ] } [/block] We're looking to have Sailthru links using HTTPS by default as soon as possible.