Set up device profiling in JavaScript apps
This page shows how to detect the DeviceProfileCallback
, how to collect the device profile, and how to send the profile to your server.
The server includes collected device information in its audit logs by default. To configure PingAM to filter out this information and ensure no personally identifiable information (PII) is written to the audit logs, refer to Prevent auditing of device data. |
Handle a device profile callback
-
Get the callback and any messages to display to the user:
const deviceCollectorCb = step.getCallbackOfType('DeviceProfileCallback'); const message = deviceCollectorCb.getMessage();
-
From the callback, determine if the intention is to collect the device location, the device metadata, or both:
const isLocationRequired = deviceCollectorCb.isLocationRequired(); const isMetadataRequired = deviceCollectorCb.isMetadataRequired();
-
Create a new instance of the
FRDevice
class.const device = new FRDevice();
To return specific device data, pass in configuration options to the
FRDevice
constructor. For example, you can return device platform, display, browser, and hardware data.
Manually collect device profile information
Instead of responding to a device callback, your app can get the device profile using default collectors.
-
Call the
getProfile()
method of theFRDevice
class, passing the boolean values from the callback that indicate if device location and/or device metadata is required:const profile = await device.getProfile({ location: isLocationRequired, metadata: isMetadataRequired, });
To return specific device data, override the FRDevice
class methods for getting the device metadata, device browser plugins, device name, device hardware, and so on. -
Set the device profile information for the step:
step.getCallbackOfType('DeviceProfileCallback').setProfile(profile);
Default collectors
Collector name | Description |
---|---|
|
Collect font information. |
|
Collect display information of the device. |
|
Collect browser information of the device. |
|
Collect hardware related information. |
|
Collect platform related information |
Sample device profile
{
"identifier": "714524572-2799534390-3707617532",
"metadata": {
"hardware": {
"cpuClass": null,
"deviceMemory": 8,
"hardwareConcurrency": 16,
"maxTouchPoints": 0,
"oscpu": null,
"display": {
"width": 1080,
"height": 1920,
"pixelDepth": 24,
"angle": 270
}
},
"browser": {
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36 Edg/80.0.361.111",
"appName": "Netscape",
"appCodeName": "Mozilla",
"appVersion": "5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36 Edg/80.0.361.111",
"appMinorVersion": null,
"buildID": null,
"product": "Gecko",
"productSub": "20030107",
"vendor": "Google Inc.",
"vendorSub": "",
"browserLanguage": null,
"plugins": "internal-pdf-viewer;mhjfbmdgcfjbbpaeojofohoefgiehjai;internal-nacl-plugin;"
},
"platform": {
"deviceName": "Mac (Browser)"
"language": "en-US",
"platform": "MacIntel",
"userLanguage": null,
"systemLanguage": null,
"fonts": "cursive;monospace;sans-serif;fantasy;Arial;Arial Black;Arial Narrow;Arial Rounded MT Bold;Comic Sans MS;Courier;Courier New;Georgia;Impact;Papyrus;Tahoma;Trebuchet MS;Verdana;",
"timezone": 300
}
},
"location": {
"latitude": 30.49843,
"longitude": -97.639371
}
}
Create a custom collector
-
Create an instance of
FRDevice
and customize the profile:const device = new FRDevice({ // Example customization: // Collect just the presence of Arial and Helvetica fontNames: [ 'Arial', 'Helvetica' ], // Do not collect any display properties displayProps: [], // Just collect User Agent browserProps: [ 'userAgent' ] });
-
Replace the methods for further customization:
device.getHardwareMeta = function () { let obj; // Custom logic to collect hardware profile obj return obj; }
-
Run the
getProfile()
method using the custom configuration and collector methods:const profile = await device.getProfile({ location: isLocationRequired, metadata: isMetadataRequired, });
Device profile attributes
By default, the Ping SDK collects the following device attributes:
Attribute | Value |
---|---|
|
A unique ID for the device. To learn more about the device identifier, refer to Uniquely identifying devices. |
|
The location of a device (longitude and latitude values). This is configured in the node and requires user permissions. |
|
Metadata for the device, including:
|
Obtain user permission for the device location
Your app requires the user’s authorization to access the device location.
If the user denies location access, the SDK still collects the device profile data; however, the collected data will not include any location coordinates.
If the user provides the permission, the SDK collects the location coordinates.
Known limitations
-
Location access requires user permissions. If the user denies permission or doesn’t respond to the browser’s request in time, geolocation coordinates are not collected and the profile is generated without it.
-
Generating the profile can take time, especially when the location is requested. If this is a step all to itself, showing a spinner with message is recommended.
-
To reduce authentication round-trips/latency, you can collect the device profile at the same time you collect other information.
-
The device profile ID is generated if one doesn’t exist, and stored in the browser’s
localStorage
. If this is done within a browser’s "private" or "incognito" mode, the ID does not persist once that window is closed. This creates a new ID, and therefore a new profile, when the profile is generated again. -
As JavaScript runs within a browser, it is more a browser profile than a device profile. A different browser on the same device produces a substantially different profile.
-
Some profile attributes are more volatile than others. Plugging an external display into a laptop, for example, alters the generated profile.