51Degrees Device Detection Node.js  4.3

51Degrees Device Detection for Node.js


This example demonstrates how to enhance results by incorporating evidence from client-side JavaScript. This approach is required to perform certain tasks such as identify iPhone and iPad models or get the screen resolution for a desktop device.

Properties containing JavaScript snippets are populated by engines in the Pipeline and these are then bundled together into a single JavaScript block by the 'JsonBuilder' and 'JavaScriptBuilder' elements. This JavaScript is then used to obtain the additional evidence from the client and pass it back to the server. The updated results can then be used immediately on the client-side or on subsequent requests to the server.

This example is available in full on GitHub.

To run this example, you will need to create a resource key. The resource key is used as shorthand to store the particular set of properties you are interested in as well as any associated license keys that entitle you to increased request limits and/or paid-for properties.

You can create a resource key using the 51Degrees Configurator.

Make sure to include the HardwareName and ScreenPixelsWidth properties as they are used by this example.

Expected output:

Updated Hardware Name from client-side evidence: Desktop,Emulator
Pixel width: 1920
/* *********************************************************************
* This Original Work is copyright of 51 Degrees Mobile Experts Limited.
* Copyright 2019 51 Degrees Mobile Experts Limited, 5 Charlotte Close,
* Caversham, Reading, Berkshire, United Kingdom RG4 7BY.
* This Original Work is licensed under the European Union Public Licence (EUPL)
* v.1.2 and is subject to its terms as set out below.
* If a copy of the EUPL was not distributed with this file, You can obtain
* one at https://opensource.org/licenses/EUPL-1.2.
* The 'Compatible Licences' set out in the Appendix to the EUPL (as may be
* amended by the European Commission) shall be deemed incompatible for
* the purposes of the Work and the provisions of the compatibility
* clause in Article 5 of the EUPL shall not apply.
* If using the Work as, or as part of, a network application, by
* including the attribution notice(s) required under Article 5 of the EUPL
* in the end user terms of the application under an appropriate heading,
* such notice(s) shall fulfill the requirements of that article.
* ********************************************************************* */
const require51 = (requestedPackage) => {
try {
return require('/../' + requestedPackage);
} catch (e) {
return require(requestedPackage);
const core = require51('fiftyone.pipeline.core');
require((process.env.directory || __dirname) +
const myResourceKey = process.env.RESOURCE_KEY || "!!YOUR_RESOURCE_KEY!!";
// We need 'server' to be defined here so that, when this example
// is executed as part of a unit test, the server can be closed
// once the test is complete.
let server;
if (myResourceKey == "!!YOUR_RESOURCE_KEY!!") {
console.log('You need to create a resource key at ' +
'https://configure.51degrees.com and paste it into the code, ' +
'replacing !!YOUR_RESOURCE_KEY!!');
} else {
// Create a new Device Detection pipeline and set the config.
// You need to create a resource key at https://configure.51degrees.com
// and paste it into the code.
// The JavaScriptBuilderSettings allow you to provide an endpoint
// which will be requested by the client side JavaScript.
// This should return the contents of the JSONBundler element which
// is automatically added to the Pipeline.
const pipeline = new DeviceDetectionCloudPipelineBuilder({
resourceKey: myResourceKey,
javascriptBuilderSettings: {
endPoint: '/json'
// Logging of errors and other messages.
// Valid logs types are info, debug, warn, error
pipeline.on('error', console.error);
const http = require('http');
server = http.createServer((req, res) => {
const flowData = pipeline.createFlowData();
// Add any information from the request
// (headers, cookies and additional client side provided information)
flowData.process().then(function () {
res.statusCode = 200;
if (req.url.startsWith('/json')) {
// Return the json to the client.
res.setHeader('Content-Type', 'application/json');
} else {
// Some browsers require that extra HTTP headers are explicitly
// requested. So set whatever headers are required by the browser in
// order to return the evidence needed by the pipeline.
// More info on this can be found at
// https://51degrees.com/blog/user-agent-client-hints
core.Helpers.setResponseHeaders(res, flowData);
// To get a more acurate list of hardware names,
// we need to run some client side javascript code.
// At first this will populate a large list which will get smaller
// following new client side evidence.
res.setHeader('Content-Type', 'text/html');
let output = '';
if (flowData.device.hardwarename && flowData.device.hardwarename.hasValue) {
console.log("Client's updated hardware name is " + flowData.device.hardwarename.value);
// If the screen pixel width has been set from the client side, output it
if (flowData.device.screenpixelswidth.hasValue && flowData.device.screenpixelswidth.value) {
console.log("Client's screen pixel width is " + flowData.device.screenpixelswidth.value);
// Print results of client side processing to the page.
output += `
<p id=hardwarename></p>
<p id=screenpixelwidth></p>
window.onload = function(){
fod.complete(function (data) {
document.getElementById('hardwarename').innerHTML = "<strong>Updated Hardware Name from client-side evidence:</strong> " + data.device["hardwarename"];
document.getElementById('screenpixelwidth').innerHTML = "<strong>Pixel width: " + data.device.screenpixelswidth + "</strong>"
// Get JavaScript to put inside the page to gather extra evidence
const js = `<script>${flowData.javascriptbuilder.javascript}</script>`;
res.end(js + output);
const port = 3000;
console.log('Server listening on port: ' + port);