upgrade-apple-device-detection-hero-image

Upgrade Apple Device Detection

Benjamin CB

9/4/2019 2:00 PM

Device Detection Apple iPhone iOS Analysis Development

Implement all the latest techniques for iOS 13 iPhone and iPad

51Degrees continue to innovate in the field of device detection. Apple iOS 12.2 made identification of iPhone and iPad models harder. 51Degrees responded with a two-part solution. The techniques and background are described in the following blogs.

  1. Image Hashing
  2. Benchmarking

The resulting JavaScript is deployed differently to previous versions of 51Degrees Apple device detection. This blog explains the differences and how to upgrade a web site to improve iPhone and iPad identification.

Differences

51Degrees favors keeping all the JavaScript associated with device detection within the device specification database. This ensures tight version control between the JavaScript and the underlying device specifications. The JavaScript is extracted at run time via the client-side override techniques explained in the developer documentation.

The JavaScript required for complete post iOS 12.2 Apple device identification uses web workers. The JavaScript solution used to date in 51Degrees device detection version 3 does not support web workers. As such an alternative solution is required.

Upgrade

51Degrees maintains the following JavaScript file for clients to add to their web pages as an include.

JavaScript file

setProfileId is the single public method provided within the JavaScript to access the feature. A cookie name and a function to call once the profile Id has been identified are passed as arguments.

Server-Side

When being deployed alongside server-side device detection APIs, the cookie name passed to setProfileId should be “51D_ProfileIds”. The script will set the cookie value to the Profile Id. The following example HTML page shows how to set the cookie and display the Profile Id.

A simple example HTML page using the JavaScript:

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Example Apple Profile Id Setter</title>
    <script defer src="https://cloud.51degrees.com/cdn/apple.min.js" type="text/javascript"></script>
    <script>
        function appleComplete(profileId) {
            document.getElementById("profileIdField").value = profileId ? profileId : 'Not Genuine Apple';
        }
        function DOMContentLoaded() {
            setProfileId('51D_ProfileIds', appleComplete);
        }
        window.addEventListener('DOMContentLoaded', DOMContentLoaded);
    </script>
</head>
<body>
    <table>
        <tr>
            <td><label for="profileIdField">Profile Id</label></td>
            <td><input type="text" id="profileIdField" /></td>
        </tr>
    </table>
</body>
</html>

Once the cookie is set subsequent page requests to the server will pass the Profile Id obtained from the apple.min.js JavaScript. 51Degrees server-side API can then be configured to override static profiles with dynamic ones - obtained from JavaScript - the device information available to the subsequent request will relate to the precise iPhone or iPad identified, or the smallest available grouping. For more information on configuring client-side overrides see the API documentation.

Client-Side Only

If the environment does not have 51Degrees deployed server-side, the device level information can be obtained via the 51Degrees cloud service using a JSON request. The following JavaScript demonstrates the technique.

Example HTML and JavaScript to obtain Apple device information:

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>iPhone and iPad Override Test</title>
    <script defer src="https://cloud.51degrees.com/cdn/apple.min.js" type="text/javascript"></script>
    <link rel="stylesheet" type="text/css" href="main.min.css">
    <script>

        // Retrieves JSON from the url.
        // @param url the URL for the JavaScript
        // @param callback function to call with the JSON result
        function getJson(url, callback) {
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            xhr.responseType = 'json';
            xhr.addEventListener("load", function () {
                var status = xhr.status;
                if (status === 200 ||
                    status === 202) {
                    callback(typeof xhr.response == "string" ?
                        JSON.parse(xhr.response) :
                        xhr.response);
                }
            });
            xhr.send();
        };

        // Fired when the device detection JavaScript is loaded.
        // @param data the JSON object which contains the response.
        function jsonComplete(data) {
            document.getElementById("deviceTypeField").value = data.device.devicetype;
            document.getElementById("hardwareVendorField").value = data.device.hardwarevendor;
            document.getElementById("hardwareNamesField").value = data.device.hardwarename;
            document.getElementById("platformNameField").value = data.device.platformname;
            document.getElementById("platformVersionField").value = data.device.platformversion;
            document.getElementById("browserNameField").value = data.device.browsername;
            document.getElementById("browserVersionField").value = data.device.browserversion;
        }

        function appleComplete(profileId) {

            // Update the field with the profile Id.
            document.getElementById("profileIdField").value = profileId ? profileId : 'Not Apple';

            // Add the new script to get the device information.
            getJson("https://cloud.51degrees.com/api/v4/<resourceKey>.json?" +
                "values=devicetype+" +
                "hardwarevendor+hardwarename+platformname+" +
                "platformversion+browsername+browserversion&" +
                (profileId ? "51D_ProfileIds=" + profileId : ""),
                jsonComplete);
        }

        function DOMContentLoaded() {
            setProfileId('51D_ProfileIds', appleComplete);
        }

        window.addEventListener('DOMContentLoaded', DOMContentLoaded);

    </script>
</head>
<body>
    <div class="c-category-header">
        <h3 class="g-info__heading">iPhone and iPad Override Test</h3>
        <p>Web page to test client side overrides</p>
    </div>
    <div class="g-info">
        <table class="g-info__table">
            <tr>
                <td><label for="profileIdField">Apple Profile Id</label></td>
                <td><input type="text" id="profileIdField" /></td>
            </tr>
            <tr>
                <td><label for="deviceTypeField">Device Type</label></td>
                <td><input type="text" id="deviceTypeField" /></td>
            </tr>
            <tr>
                <td><label for="hardwareVendorField">Device Vendor</label></td>
                <td><input type="text" id="hardwareVendorField" /></td>
            </tr>
            <tr>
                <td><label for="hardwareNamesField">Device Name(s)</label></td>
                <td><textarea id="hardwareNamesField" rows="4"></textarea></td>
            </tr>
            <tr>
                <td><label for="platformNameField">OS Name</label></td>
                <td><input type="text" id="platformNameField" /></td>
            </tr>
            <tr>
                <td><label for="platformVersionField">OS Version</label></td>
                <td><input type="text" id="platformVersionField" /></td>
            </tr>
            <tr>
                <td><label for="browserNameField">Browser Name</label></td>
                <td><input type="text" id="browserNameField" /></td>
            </tr>
            <tr>
                <td><label for="browserVersionField">Browser Version</label></td>
                <td><input type="text" id="browserVersionField" /></td>
            </tr>
        </table>
    </div>
    <div class="g-footer">
        <p class="g-footer__copyright">Copyright © 2019 51Degrees</p>
    </div>
</body>
</html>

Google Analytics custom dimensions can be used with the above code to map the JSON data passed to the function jsonComplete.

Summary

Many of the use cases for identifying Apple devices involve supporting analytics and user profiling. The solutions shown in this blog provide easy to deploy options for web developers seeking to use an entire client-side solution, or for customers who value enterprise level performance with a server-side option.

If you'd like to know more about upgrading to 51Degrees device detection, and the solution demonstrated in the blog then please contact us.

The full Apple identification solution is part of 51Degrees device detection suite of services. Save the hassle of rolling your own solution and deploy 51Degrees today and get access to over 55,000 different device models with associated properties.