# DeviceAtlas Client-side Component # DeviceAtlas provides an optional client-side JavaScript library for gathering additional properties using JavaScript. This library can send the gathered properties back to the DeviceAtlas API running on a web server. The JavaScript properties are then used to augment the regular DeviceAtlas properties and allow for additional capabilities like fine-grained Apple device detection and support for User-Agent Client Hints. The client properties are also available to other JavaScript libraries. The DeviceAtlas client detection file needs to be included on your web page for this to function. Full documentation and example code are included in the API packages. ## Introduction ## DeviceAtlas uses HTTP headers to accurately identify devices. This is achieved by passing the headers to a server-side DeviceAtlas API. The API then uses the headers to determine the correct set of properties for the request. These properties are then returned to the calling application. This approach is suitable for the vast majority of cases except for three situations: 1. Apple Devices: The data passed from Apple devices in the HTTP headers does not contain any information to indicate which specific model is accessing the server. It only shows if it is an iPhone, iPad or iPod Touch but not, for example, if it's an iPhone 14 or an iPhone 15. This is a large problem if device specific data is required for these devices. Client-side data can be used to augment the server-side DeviceAtlas data to more accurately identify Apple devices. 2. User-Agent Client Hints: Google's [User-Agent Client Hints initiative](https://wicg.github.io/ua-client-hints/) removes granular browser and device information from the standard User-Agent string and makes it available via a set of additional HTTP headers and a JavaScript API. The additional headers must be requested with an `Accept-CH` response header sent by the web server to the browser. For cases where this configuration is not possible the DeviceAtlas Client-side Component can be utilised to obtain client hint data from the browser via JavaScript. 3. Contextual information: Client-side data can help indicate the current context of the user/device such as the current device orientation of the device or if the user has cookies enabled. It can also improve the server-side property set for JavaScript and HTML5 properties for less well-known browsers. ## Client-side Component ## The DeviceAtlas client-side component is a small JavaScript library that can be included on a webpage. The library gathers client-side properties and optionally creates a cookie containing the data. The cookie is used as a means of transferring the client-side data to the server but alternative approaches can be used such as sending the data in an Ajax request. The client-side data sent to the server must then be passed to the DeviceAtlas API along with the device HTTP headers. The API will use the HTTP headers and the client-side properties to detect Apple Devices. The resulting property set contains the merged server and client side properties. ``` +---------+ +---------+ +-------------+ | Browser | | Server | | DeviceAtlas | +---------+ +---------+ +-------------+ | | | | GET | | |-------------------------------------->| | | | | | | getProperties(headers) | | |--------------------------------------------------->| | | | | | initial properties | | |<---------------------------------------------------| | | | | response + client-side component | | |<--------------------------------------| | | | | | client-side component runs | | |--------------------------- | | | | | | |<-------------------------- | | | | | | GET + client-side result | | |-------------------------------------->| | | | | | | getProperties(headers + client-side result) | | |--------------------------------------------------->| | | | | | full properties | | |<---------------------------------------------------| | | | | response | | |<--------------------------------------| | | | | | | | ``` ### Client-side Access to Properties ### The properties gathered by the client-side component are available to other JavaScript functions and can be accessed on the client-side by using the "DeviceAtlas" namespace. **Example:** ```JavaScript // Does the browser support Web GL ? var supportsWebGl = DeviceAtlas.js.webGl; ``` The normal DeviceAtlas property name should be used to access the client-side property. A full list of the client side properties can be found on the [DeviceAtlas website](https://deviceatlas.com/resources/client-side-properties). ### Server-side Access to Properties ### The client-side component creates a special cookie with the detected client properties. This cookie is used as a way to transmit the properties back to the server. Other approaches such as AJAX could also be used. The usage of the properties via the cookie is different in the Enterprise and Cloud APIs. By default, the cookie containing the properties is called "DAPROPS". #### Use with Enterprise API #### If the cookie is available and the DeviceApiWeb extension is used, the API will automatically use the cookie contents as a part of the detection. However it is also possible to pass the client-side properties manually to the APIs. Please refer to the technical API development documentation for details. Apache / NGINX / IIS web server modules handle the cookie automatically. ** Compatibility requirements ** For correct functionality an up-to-date JSON file and the following Enterprise API versions are required. - Java: 1.6 or later - Node.js: 2.1 or later - PHP: 1.6 or later - .NET: 1.6 or later - Python: 1.6 or later - C++: 2.1.2 or later - C: 2.1.2 or later #### Use with Cloud API #### If the cookie is available and the API is configured to use the cookie, the API will automatically forward the cookie contents to the Cloud service and will be used as a part of the detection. Please refer to the technical API development documentation for details. ** Compatibility requirements ** For correct functionality the Cloud API 1.3 version or later is required. ### Basic Server-side Usage ### 1. Include the https://cs.deviceatlas-cdn.com/dacs.js javascript file on a web page. 2. In the server-side web application, pass the contents of the DeviceAtlas cookie to the DeviceAtlas API. NOTE: the cookie contents will only be set **after** the first request. It is recommended to not rely on the client-side properties for the very first page load. Please see the Example code bundled with the API for more information. ### Custom Configuration ### To customize the cookie name or other cookie parameters like domain or a path you can use the configuration code below - this code must be included before the client-side javascript file. In case of restricted cookies access usage of `onPropertiesUpdate` field is strongly recommended in order to retrieve the complete set of properties - when detecting iPhone `audioRef` property is required. ```JavaScript <script type="text/javascript"> var DeviceAtlas = { cookieName: 'DAPROPS', // the cookie name cookieExpiryDays: 1, // the time cookie expires in days cookieDomain: '.yourdomain.tld', // custom domain cookiePath: '/', // custom path debug: false, // expects bool|function - default false, pass true to use console.log or pass any callback function cacheType: 'cookie', // cache type to store test results - available options 'cookie', 'local-storage', 'none' cacheKey: 'DAPROPS', // cache key for storing client-side test results on browser cacheExpiryDays: 1, // the time cache expires in days waitMilliSecondsToBulkSendProperties: 3000, // max wait (to get properties resolved) in miliseconds before firing onPropertiesUpdate dontStopPropertyUpdateEvents: false, // only one onPropertiesUpdate event is sent, set true to keep getting onPropertiesUpdate onPropertiesUpdate: function(properties, propertiesAsString) { // expects function - default undefined, pass function to capture properties updates // properties will be object containing all properties detected by DeviceAtlas client-side // propertiesAsString would have properties as string acceptable by DeviceAtlas API }, } </script> <script type="text/javascript" src="https://cs.deviceatlas-cdn.com/dacs.js" async></script> ``` ### Browser Results Cache Types ### Cookies or Local Storage works as cache to avoid re-running tests. Few differences when using cookie or local storage. - Using cacheType=cookie tests are saved in cookie, cookie name can be configured in cookieName config, - on every page load client-side library will determine tests to run/skip based on results saved in cookies from previous runs. - all further requests from browser will have Cookie string attached to request (in Cookie header) automatically by browser, to be passed to DeviceAtlas API on server side. - user can also use onPropertiesUpdate callback function to pass client-side string to DeviceAtlas API on server side. - Using cacheType=local-storage tests are saved in local-storage, local sorage key can be configured in cacheKey config, - on every page load client-side library will determine tests to run/skip based on results saved in local-storage from previous runs. - to results back to DeviceAtlas API on server side users will have to use onPropertiesUpdate callback function. - Using cacheType=none tests results are evalulated on every page load. - on every page load client-side library will re-run tests. - to results back to DeviceAtlas API on server side users will have to use onPropertiesUpdate callback function. ### Sending client-side data ### In a restricted environment where cookies are not allowed it is possible to get the client-side data using the onPropertiesUpdate event method and passing propertiesAsString as a URL parameter. onPropertiesUpdate event will be fired - if all properties required for Apple Devices Detection are resolved - if max wait time exceeds when waiting on required for Apple Devices Detection to be resolved check configs waitMilliSecondsToBulkSendProperties, dontStopPropertyUpdateEvents Local Storage can be used to cache client side test results on user's browser, check cacheType config. NOTE: When integrating with a web application, the value should be fetched from the URL and passed to the DeviceAtlas API. **Example:** ``` <!DOCTYPE html> <html> <head> </head> <body> <script type="text/javascript"> var DeviceAtlas = { onPropertiesUpdate: function(properties, propertiesAsString) { // user-agent and other headers are automatically added by browser on request to server side // if using cookie as cache, Cookie header is automatically added to requests by browser // for local-storage or no cache, client-side properties can be passed via header or GET/POST parameter to server side running DeviceAtlas API // below client-side string is being passed via DeviceAtlas-Client-Side-String header // DeviceAtlas API on server-side would need to read the header and pass client-side properties in API's getProperties method var req = new XMLHttpRequest(); req.onreadystatechange = function() { if (req.readyState == XMLHttpRequest.DONE) { // req.responseText here would hold detected device properties // from DeviceAtlas API lookup on server side console.log(req.responseText); } } req.open('GET', './deviceatlas-api-on-server-side', true); req.setRequestHeader('DeviceAtlas-Client-Side-String', propertiesAsString); req.send(null); } } </script> <script type="text/javascript" src="https://cs.deviceatlas-cdn.com/dacs.js" async></script> </body> </html> ``` ### Identification of Apple devices ### The DeviceAtlas Client-side Component augments the server side properties and allows for accurate identification of Apple devices. The following variants of iPhone and iPad models are identified. Please note there is a small selection of older devices that cannot be identified fully. In this case, all of the possible model names are returned. | Model | Model Identifiers | Year Released | Primary Hardware Type | Without Client-side | With Client-side | |:---------------------------|:--------------------------------------------|----------------:|:------------------------|:----------------------|:---------------------------------------------------------------------------------| | iPhone 16 | iPhone17,3 | 2024 | Mobile Phone | iPhone | iPhone 15 Pro/iPhone 16 | | iPhone 16 Plus | iPhone17,4 | 2024 | Mobile Phone | iPhone | iPhone 15 Pro Max/iPhone 16 Plus | | iPhone 16 Pro | iPhone17,1 | 2024 | Mobile Phone | iPhone | iPhone 16 Pro | | iPhone 16 Pro Max | iPhone17,2 | 2024 | Mobile Phone | iPhone | iPhone 16 Pro Max | | iPad Air (11 6th Gen) | iPad14,8/iPad14,9 | 2024 | Tablet | iPad | iPad Air 4/iPad Air 5/iPad Air (11 6th Gen) | | iPad Air (13 6th Gen) | iPad14,10/iPad14,11 | 2024 | Tablet | iPad | iPad Pro (12.9 5th Gen)/iPad Pro (12.9 6th Gen)/iPad Air (13 6th Gen) | | iPad Pro (11 5th Gen) | iPad16,3/iPad16,4 | 2024 | Tablet | iPad | iPad Pro (11 5th Gen) | | iPad Pro (13 7th Gen) | iPad16,5/iPad16,6 | 2024 | Tablet | iPad | iPad Pro (13 7th Gen) | | iPhone 15 | iPhone15,4 | 2023 | Mobile Phone | iPhone | iPhone 14 Pro/iPhone 15 | | iPhone 15 Plus | iPhone15,5 | 2023 | Mobile Phone | iPhone | iPhone 14 Pro Max/iPhone 15 Plus | | iPhone 15 Pro | iPhone16,1 | 2023 | Mobile Phone | iPhone | iPhone 15 Pro/iPhone 16 | | iPhone 15 Pro Max | iPhone16,2 | 2023 | Mobile Phone | iPhone | iPhone 15 Pro Max/iPhone 16 Plus | | iPad (10th Gen) | iPad13,18/iPad13,19 | 2022 | Tablet | iPad | iPad (10th Gen) | | iPad Air 5 | iPad13,16/iPad13,17 | 2022 | Tablet | iPad | iPad Air 4/iPad Air 5/iPad Air (11 6th Gen) | | iPad Pro (11 4th Gen) | iPad14,3/iPad14,4 | 2022 | Tablet | iPad | iPad Pro (11 3rd Gen)/iPad Pro (11 4th Gen) | | iPad Pro (12.9 6th Gen) | iPad14,5/iPad14,6 | 2022 | Tablet | iPad | iPad Pro (12.9 5th Gen)/iPad Pro (12.9 6th Gen)/iPad Air (13 6th Gen) | | iPhone 14 | iPhone14,7 | 2022 | Mobile Phone | iPhone | iPhone 13/iPhone 13 Pro/iPhone 14 | | iPhone 14 Plus | iPhone14,8 | 2022 | Mobile Phone | iPhone | iPhone 13 Pro Max/iPhone 14 Plus | | iPhone 14 Pro | iPhone15,2 | 2022 | Mobile Phone | iPhone | iPhone 14 Pro/iPhone 15 | | iPhone 14 Pro Max | iPhone15,3 | 2022 | Mobile Phone | iPhone | iPhone 14 Pro Max/iPhone 15 Plus | | iPhone SE (3rd generation) | iPhone14,6 | 2022 | Mobile Phone | iPhone | iPhone SE (3rd generation) | | iPad (9th Gen) | iPad12,1/iPad12,2/ipad12,1 | 2021 | Tablet | iPad | iPad (9th Gen) | | iPad mini 6 | iPad14,1/iPad14,2 | 2021 | Tablet | iPad | iPad mini 6 | | iPad Pro (11 3rd Gen) | iPad13,5/iPad13,6/iPad13,7/iPad13,4 | 2021 | Tablet | iPad | iPad Pro (11 3rd Gen)/iPad Pro (11 4th Gen) | | iPad Pro (12.9 5th Gen) | iPad13,10/iPad13,11/iPad13,9/iPad13,8 | 2021 | Tablet | iPad | iPad Pro (12.9 5th Gen)/iPad Pro (12.9 6th Gen)/iPad Air (13 6th Gen) | | iPhone 13 | iPhone14,5 | 2021 | Mobile Phone | iPhone | iPhone 13/iPhone 13 Pro/iPhone 14 | | iPhone 13 mini | iPhone14,4 | 2021 | Mobile Phone | iPhone | iPhone 13 mini/iPhone 13 Pro Max/iPhone 14 Plus/iPhone 14 Pro Max/iPhone 15 Plus | | iPhone 13 Pro | iPhone14,2 | 2021 | Mobile Phone | iPhone | iPhone 13/iPhone 13 Pro/iPhone 14 | | iPhone 13 Pro Max | iPhone14,3 | 2021 | Mobile Phone | iPhone | iPhone 13 Pro Max/iPhone 14 Plus | | iPad (8th Gen) | iPad11,6/iPad11,7 | 2020 | Tablet | iPad | iPad (8th Gen) | | iPad Air 4 | iPad13,1/iPad13,2 | 2020 | Tablet | iPad | iPad Air 4/iPad Air 5/iPad Air (11 6th Gen) | | iPad Pro (11 2nd Gen) | iPad8,9/iPad8,10 | 2020 | Tablet | iPad | iPad Pro (11)/iPad Pro (11 2nd Gen) | | iPad Pro (12.9 4th Gen) | iPad8,11/iPad8,12 | 2020 | Tablet | iPad | iPad Pro (12.9 3rd Gen)/iPad Pro (12.9 4th Gen) | | iPhone 12 | iPhone13,2 | 2020 | Mobile Phone | iPhone | iPhone 12/iPhone 12 Pro | | iPhone 12 Mini | iPhone13,1 | 2020 | Mobile Phone | iPhone | iPhone 12 Mini/iPhone 12 Pro Max | | iPhone 12 Pro | iPhone13,3 | 2020 | Mobile Phone | iPhone | iPhone 12/iPhone 12 Pro | | iPhone 12 Pro Max | iPhone13,4 | 2020 | Mobile Phone | iPhone | iPhone 12 Pro Max | | iPhone SE (2nd generation) | iPhone12,8 | 2020 | Mobile Phone | iPhone | iPhone SE (2nd generation) | | iPad (7th Gen) | iPad7,11/iPad7,12 | 2019 | Tablet | iPad | iPad (7th Gen) | | iPad Air 3 | iPad11,3/iPad11,4 | 2019 | Tablet | iPad | iPad Air 3 | | iPad mini 5 | iPad11,1/iPad11,2 | 2019 | Tablet | iPad | iPad mini 5 | | iPhone 11 | iPhone12,1 | 2019 | Mobile Phone | iPhone | iPhone 11 | | iPhone 11 Pro | iPhone12,3 | 2019 | Mobile Phone | iPhone | iPhone 11 Pro/iPhone 11 Pro Max | | iPhone 11 Pro Max | iPhone12,5 | 2019 | Mobile Phone | iPhone | iPhone 11 Pro Max | | iPad (6th Gen) | iPad7,5/iPad7,6/ipad7,5 | 2018 | Tablet | iPad | iPad (5th Gen)/iPad (6th Gen) | | iPad Pro (11) | iPad8,1/iPad8,2/iPad8,3/iPad8,4 | 2018 | Tablet | iPad | iPad Pro (11)/iPad Pro (11 2nd Gen) | | iPad Pro (12.9 3rd Gen) | iPad8,5/iPad8,6/iPad8,7/iPad8,8 | 2018 | Tablet | iPad | iPad Pro (12.9 3rd Gen)/iPad Pro (12.9 4th Gen) | | iPhone XR | iPhone11,8/iphone11,8 | 2018 | Mobile Phone | iPhone | iPhone XR | | iPhone XS | iPhone11,2/iphone11,2 | 2018 | Mobile Phone | iPhone | iPhone XS/iPhone XS Max | | iPhone XS Max | iPhone11,4/iPhone11,6/iphone11,6 | 2018 | Mobile Phone | iPhone | iPhone XS Max | | iPad (5th Gen) | iPad6,11/iPad6,12/ipad6,12 | 2017 | Tablet | iPad | iPad (5th Gen)/iPad (6th Gen) | | iPad Pro (10.5) | iPad7,3/iPad7,4 | 2017 | Tablet | iPad | iPad Pro (10.5) | | iPad Pro (12.9 2nd Gen) | iPad7,1/iPad7,2 | 2017 | Tablet | iPad | iPad Pro (12.9 2nd Gen) | | iPhone 8 | iPhone10,1/iPhone10,4/iphone10,1/iphone10,4 | 2017 | Mobile Phone | iPhone | iPhone 8 | | iPhone 8 Plus | iPhone10,2/iPhone10,5/iphone10,5/iphone10,2 | 2017 | Mobile Phone | iPhone | iPhone 8 Plus | | iPhone X | iPhone10,3/iPhone10,6/iphone10,3/iphone10,6 | 2017 | Mobile Phone | iPhone | iPhone X | | iPad Pro (9.7) | iPad6,3/iPad6,4 | 2016 | Tablet | iPad | iPad Pro (9.7) | | iPhone 7 | iPhone9,1/iPhone9,3/iphone9,1/iphone9,3 | 2016 | Mobile Phone | iPhone | iPhone 7 | | iPhone 7 Plus | iPhone9,2/iPhone9,4/iphone9,4/iphone9,2 | 2016 | Mobile Phone | iPhone | iPhone 7 Plus | | iPhone SE | iPhone8,4/iphone8,4 | 2016 | Mobile Phone | iPhone | iPhone SE | | iPad mini 4 | iPad5,1/iPad5,2/ipad5,2 | 2015 | Tablet | iPad | iPad Air 2/iPad mini 4 | | iPad Pro | iPad6,7/iPad6,8 | 2015 | Tablet | iPad | iPad Pro | | iPhone 6S | iPhone8,1/iphone8,1 | 2015 | Mobile Phone | iPhone | iPhone 6S | | iPhone 6S Plus | iPhone8,2/iphone8,2 | 2015 | Mobile Phone | iPhone | iPhone 6S Plus | | iPad Air 2 | iPad5,3/iPad5,4/ipad5,3 | 2014 | Tablet | iPad | iPad Air 2/iPad mini 4 | | iPad mini 3 | iPad4,7/iPad4,8/iPad4,9 | 2014 | Tablet | iPad | iPad Air/iPad mini 2/iPad mini 3 | | iPhone 6 | iPhone7,2/iphone7,2 | 2014 | Mobile Phone | iPhone | iPhone 6 | | iPhone 6 Plus | iPhone7,1 | 2014 | Mobile Phone | iPhone | iPhone 6 Plus | | iPad Air | iPad4,1/iPad4,2/iPad4,3 | 2013 | Tablet | iPad | iPad Air/iPad mini 2/iPad mini 3 | | iPad mini Retina | iPad4,4/iPad4,5/iPad4,6 | 2013 | Tablet | iPad | iPad Air/iPad mini 2/iPad mini 3 | | iPhone 5C | iPhone5,4/iPhone5,3 | 2013 | Mobile Phone | iPhone | iPhone 5/iPhone 5C | | iPhone 5S | iPhone6,2/iPhone6,1 | 2013 | Mobile Phone | iPhone | iPhone 5S | | iPad Retina (3rd Gen) | iPad3,3/iPad3,1/iPad3,2 | 2012 | Tablet | iPad | iPad Retina (3rd Gen) | | iPad mini | iPad2,5/iPad2,6/iPad2,7 | 2012 | Tablet | iPad | iPad 2/iPad mini | | iPad Retina (4th Gen) | iPad3,4/iPad3,5/iPad3,6 | 2012 | Tablet | iPad | iPad Retina (4th Gen) | | iPhone 5 | iPhone5,1/iPhone5,2 | 2012 | Mobile Phone | iPhone | iPhone 5/iPhone 5C | | iPad 2 | iPad2,2/iPad2,1/iPad2,3/iPad2,4 | 2011 | Tablet | iPad | iPad 2/iPad mini | | iPhone 4S | iPhone4,1 | 2011 | Mobile Phone | iPhone | iPhone 4S | | iPad | iPad1,1 | 2010 | Tablet | iPad | iPad | | iPhone 4 | iPhone3,3/iPhone3,1/iPhone3,2 | 2010 | Mobile Phone | iPhone | iPhone 4 | | iPhone 3GS | iPhone2,1 | 2009 | Mobile Phone | iPhone | iPhone/iPhone 3G/iPhone 3GS | | iPhone 3G | iPhone1,2 | 2008 | Mobile Phone | iPhone | iPhone/iPhone 3G/iPhone 3GS | | iPhone | iPhone1,1 | 2007 | Mobile Phone | iPhone | iPhone/iPhone 3G/iPhone 3GS | ### Adding device properties ### The capabilities of the Client-side component can be customized by adding or replacing functions to detect device properties. **Example:** ```JavaScript <script type="text/javascript"> /** * Adding property to see if it's a modern browser: * * For more details: https://www.w3.org/TR/html5/ */ var DeviceAtlas = { properties: { isModernBrowser: function(isModernBrowserValueFromCache, asyncDoneCallback, detectedProperties) { return detectedProperties.cookieSupport && detectedProperties.js.webWorkers && detectedProperties.js.webSockets && detectedProperties.css.animations && detectedProperties.html.video && detectedProperties.html.svg && detectedProperties.js.webGl && detectedProperties.js.localStorage; } } } </script> <script type="text/javascript" src="https://cs.deviceatlas-cdn.com/dacs.js" async></script> ``` ### Client-side Component Variants ### #### Standard Library #### The standard version of the Client-side Component is distributed via CDN here https://cs.deviceatlas-cdn.com/dacs.js. It provides the detection of [the full property set](https://deviceatlas.com/resources/client-side-properties). #### Lite Variant #### The Lite variant, a subset of the standard component for optimization purposes, is distributed in via https://cs.deviceatlas-cdn.com/dacs-lite.js. It solely identifies those device properties that are required to distinguish the underlying hardware of iOS based devices. #### Custom Build #### From the DeviceAtlas site, a customized Client-side component with a subset of properties can be created tailored to specific needs. The resulting JavaScript file will be optimized in terms of size and speed to improve end-user experience. Please see the [DeviceAtlas Client-side Component generator](https://deviceatlas.com/resources/clientside). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _ Copyright (c) DeviceAtlas Limited 2024. All Rights Reserved. _ https://deviceatlas.com <!-- HTML+JS for document formatting when opened in browser -->