CloudPage Deep Linking
A dynamic deep linking solution that routes users based on device type.
I know what you're thinking: SFMC already has deep linking configurations built-in, so why do I need this? Well, maybe you weren't thinking that, but it's a great question!
While using features, such as iOS Universal Links, might be sufficient for most users, there are use-cases in which the desired functionality requires more flexibility. Let's say we want custom routing based on device type or a universal link for both Android and iOS devices. How can we determine the device type and direct users where we want them to go? In order to implement that functionality, we'll need to turn to user agents.
User Agent
A user agent is a string that your internet browser sends to the web server it’s communicating with, describing your operating system, browser, rendering engine, and other important details. This information is passed to web servers via HTTP headers and can be used to dynamically render content based on the type of device or OS that the request is being made from. To get a better idea of what this looks like, let's take a look at the following example:
Mozilla/5.0 (Windows NT 10.0; Win 64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.88 Safari/537.36
Browser: Chrome (version 79; patch 3945)
Device: PC (Windows 10 64-bit)
Rendering Engine: AppleWebKit
By parsing the above user agent string, we were able to extract the browser, device type and rendering engine of the request. For more information on user agents, or to see more examples, please refer to the [MDN document](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/user agent) on this subject.
How Can We Use This Information?
So, now that we have found a way to get a user's browser and device type, we can start to implement our solution. First, we're going to need a script for retrieving, and parsing, the user agent in order to determine where the request is coming from.
Creating the Device Detection Script
First, let's create a Javascript Code Resource CloudPage in order to house our user agent detection script. Once that's set up, we'll drop in the following script and save the page.
DeviceDetection = function(ua) {
this.ua;
this.checks;
this.construct = function(ua) {
if (typeof ua == 'undefined') { var ua = navigator.userAgent; }
this.ua = ua;
// parse data
this.checks = {
iphone: Boolean(ua.match(/iPhone/)),
ipod: Boolean(ua.match(/iPod/)),
ipad: Boolean(ua.match(/iPad/)),
blackberry: Boolean(ua.match(/BlackBerry/)),
playbook: Boolean(ua.match(/PlayBook/)),
android: Boolean(ua.match(/Android/)),
macOS: Boolean(ua.match(/Mac OS X/)),
win: Boolean(ua.match(/Windows/)),
mac: Boolean(ua.match(/Macintosh/)),
wphone: Boolean(ua.match(/(Windows Phone OS|Windows CE|Windows Mobile)/)),
mobile: Boolean(ua.match(/Mobile/)),
androidTablet: Boolean(ua.match(/(GT-P1000|SGH-T849|SHW-M180S)/)),
tabletPc: Boolean(ua.match(/Tablet PC/)),
palmDevice: Boolean(ua.match(/(PalmOS|PalmSource| Pre\/)/)),
kindle: Boolean(ua.match(/(Kindle)/)),
otherMobileHints: Boolean(ua.match(/(Opera Mini|IEMobile|
SonyEricsson|smartphone)/)),
};
}
this.isTouchDevice = function() {
return this.checks.iphone || this.checks.ipod || this.checks.ipad;
}
this.isApple = function() {
return this.checks.iphone || this.checks.ipod || this.checks.ipad
|| this.checks.macOS || this.checks.mac;
}
this.isBlackberry = function() {
return this.checks.blackberry;
}
this.isAndroid = function() {
return this.checks.android;
}
this.isTablet = function() {
return this.checks.ipad || this.checks.tabletPc || this.checks.playbook
|| this.checks.androidTablet || this.checks.kindle;
}
this.isDesktop = function() {
return !this.isTouchDevice() && !this.isSmartPhone() && !this.isTablet()
}
this.isSmartPhone = function() {
return (this.checks.mobile || this.checks.blackberry || this.checks.palmDevice
|| this.checks.otherMobileHints) && !this.isTablet() && !this.checks.ipod;
}
this.construct(ua);
}
In the above script we are doing a few different things. First, we're grabbing the user agent from the HTTP header and assigning it to a variable using var ua = navigator.userAgent;
. Then, we use regular expressions to check each device type to determine if the user agent string contains matches that identify it as that particular type. Once we have ran this check, we'll use some simple functions to categorize our device type into a more general classification that we can use to direct users.
Now that we've got a script to retrieve the user agent and to categorize the device, we'll need to create another CloudPage that will actually redirect the user to the correct location.
Creating Redirection CloudPage
For this step, we'll set up a standard CloudPage and then drop in this markup that will allow us to run the script from the previous step and then direct the user to the right location based on its results.
<html>
<body>
<!--[if IE]>
<script type="text/javascript">
window.location = 'http://mobileapp.sampleapp.com/';
</script>
[endif]-->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="deviceDetection.js"></script>
<script type="text/javascript">
$(function() {
var detection = new DeviceDetection(navigator.userAgent);
if (detection.isApple() && !detection.isDesktop()) {
document.location = 'sampleapp://mobile/?fid=CI&confirmationno=';
setTimeout(function() {
window.location = 'https://itunes.apple.com/us/app/sampleapp/id12345678?mt=9';
}, 500);
}
if (detection.isAndroid()) {
document.location = 'sampleapp://mobile/?fid=CI&confirmationno=%';
setTimeout(function() {
window.location = 'https://play.google.com/store/apps/details?id=sampleapp.mrt&hl=en';
}, 800);
}
if (detection.isDesktop()) {
window.location = 'http://mobileapp.sampleapp.com/';
}
});
</script>
</body>
</html>
There are a few pieces to unpack in this markup, so let's break them down into separate snippets and analyze each one:
<!--[if IE]>
<script type="text/javascript">
window.location = 'http://mobileapp.sampleapp.com/';
</script>
[endif]-->
Here we're going to isolate IE users due to browser incompatibility with our approach. These users will automatically be redirected to our app landing page.
var detection = new DeviceDetection(navigator.userAgent);
if (detection.isApple() && !detection.isDesktop()) {
document.location = 'sampleapp://mobile/?fid=CI&confirmationno=';
setTimeout(function() {
window.location = 'https://itunes.apple.com/us/app/sampleapp/id12345678?mt=9'; }, 800);}
In this portion, we're going to initialize our user agent string detection script and determine if the device type is an apple device but not a desktop computer. We'll also use the setTimeout()
function in order to determine whether the user has our application installed on their phone currently. If the redirection to the mobile app deep link is not successful after 800 milliseconds, then we'll revert to the iTunes store for our application. This ensures that we provide a suitable fallback for users who don't already have our application or if there is an issue connecting to the app.
if (detection.isAndroid()) {
document.location = 'sampleapp://mobile/?fid=CI&confirmationno=%';
setTimeout(function() {
window.location = 'https://play.google.com/store/apps/details?id=sampleapp.mrt&hl=en';
}, 800);}
This snippet is similar to the previous one in functionality except that we are now checking whether the request is coming from an Android device rather than an apple one. Note that, because Apple operates both desktop and mobile devices while Android is mobile-only, the isDesktop()
check is not necessary for this type.
if (detection.isDesktop()) {
window.location = 'http://mobileapp.sampleapp.com/';
}
Finally, we're checking to see if the user device type is a desktop computer. If so, we'll redirect them to our application landing page so that they can get further information about our sample app.
Add CloudPage Link To Email
Now that we have our detection script and redirect CloudPage in place, it's time to add this functionality to our email send! To do this, all we need to do is identify the button or link that you would like to deep link and substitute your existing URL for the following (assuming the CloudPage ID is 123 in this example):
%%=CloudPagesURL("123")=%%
Conclusion
That's it! With this solution, we are now able to dynamically deep link our user's to the appropriate version of our application while having a solid fallback in place to handle any contingencies. In addition to this blog post, you can find the code for this example in this github repository.