Getting started example of using 51Degrees device detection with User-Agent HTTP header values and User Agent Client Hint (UACH) header values.
Getting started example of using 51Degrees device detection with User-Agent HTTP header values and User Agent Client Hint (UACH) header values.The example shows how to:
- Specify the name of the data file, properties the data set should be initialised with, and the configuration. using namespace FiftyoneDegrees;string fileName = "51Degrees-V4.1.hash";string propertiesString ="ScreenPixelsWidth,IsMobile,BrowserName,PlatformName,PlatformVersion,""SetHeaderPlatformAccept-CH";Common::RequiredPropertiesConfig *properties =new Common::RequiredPropertiesConfig(&propertiesString);DeviceDetection::Hash::DeviceDetection::Hash::ConfigHash *config =new DeviceDetection::Hash::DeviceDetection::Hash::ConfigHash();C++ class wrapper for the fiftyoneDegreesPropertiesRequired structure.Definition RequiredPropertiesConfig.hpp:59A C++ wrapper class for transform.h conversion routines.Definition ComponentMetaDataBuilderHash.hpp:33
- Construct a new engine from the specified data file with the required properties and the specified configuration. using namespace FiftyoneDegrees;DeviceDetection::Hash::EngineHash *engine =dataFilePath,config,properties);Encapsulates the Hash engine class which implements EngineDeviceDetection.Definition EngineHash.hpp:96
3a. Create a evidence instance and add a single HTTP User-Agent string to be processed.
using namespace FiftyoneDegrees;
evidence->operator[]("header.user-agent") = userAgent;
Device detection specific evidence class containing evidence to be processed by a device detection en...
Definition EvidenceDeviceDetection.hpp:64
Definition GettingStarted.c:67
3b. Where UACH headers are being used add evidence for the Sec-CH-UA-Platform and Sec-CH-UA-Platform-Version HTTP header values.
using namespace FiftyoneDegrees;
evidence->operator[]("header.Sec-CH-UA-Platform") = uachPlatform;
evidence->operator[]("header.Sec-CH-UA-Platform-Version")= uachPlatformVersion;
- Process the evidence using the engine to retrieve the values associated with the User-Agent for the selected properties.
5a. Extract the value of the IsMobile property as a string from the results.
if (value.hasValue()) {
string value = *value;
}
fiftyoneDegreesValue Value
Synonym for fiftyoneDegreesValue type.
Definition common/fiftyone.h:165
5b. If using UACH example then get the platform name and version.
Value<string> value = results->getValueAsString("PlatformName");
if (value.hasValue()) {
string value = *value;
Value<string> value = results->getValueAsString("PlatformVersion");
if (value.hasValue()) {
string value = *value;
- Release the memory used by the results and the evidence. delete results;delete evidence;
- Finally release the memory used by the engine. delete engine;
/* *********************************************************************
* This Original Work is copyright of 51 Degrees Mobile Experts Limited.
* Copyright 2026 51 Degrees Mobile Experts Limited, Davidson House,
* Forbury Square, Reading, Berkshire, United Kingdom RG1 3EU.
*
* 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.
* ********************************************************************* */
#include "ExampleBase.hpp"
using namespace FiftyoneDegrees::Examples::Hash;
namespace FiftyoneDegrees {
namespace Examples {
namespace Hash {
public:
};
Common::Value<string> value;
value.getValue() :
value = results->getValueAsString("PlatformVersion");
cout << "\tPlatformVersion: " << (value.hasValue() ?
value.getValue() :
value.getNoValueMessage()) << "\n";
value = results->getValueAsString("IsMobile");
cout << "\tIsMobile: " << (value.hasValue() ?
value.getValue() :
value.getNoValueMessage()) << "\n";
}
// Create an evidence instance to store and process
// User-Agents.
EvidenceDeviceDetection *evidence =
new EvidenceDeviceDetection();
cout << "Starting Getting Started Example.\n";
std::string deviceId_mobile;
{
evidence->clear();
// Carries out a match for a mobile User-Agent.
cout << "\n";
cout << "Mobile User-Agent: " <<
evidence->operator[]("header.user-agent")
printResults(results);
deviceId_mobile = results->getDeviceId();
delete results;
};
{
evidence->clear();
// Carries out a match for a desktop User-Agent.
cout << "\n[---]\n";
cout << "Desktop User-Agent: " <<
evidence->operator[]("header.user-agent")
printResults(results);
delete results;
};
{
evidence->clear();
// Carries out a match for a MediaHub User-Agent.
cout << "\n[---]\n";
cout << "MediaHub User-Agent: " <<
evidence->operator[]("header.user-agent")
printResults(results);
delete results;
};
std::string deviceId_hintedHub;
{
evidence->clear();
// Carries out a match for a platform based on UACH headers.
cout << "\n(+)\n";
cout << "UACH Sec-CH-UA-Platform: " <<
cout << "UACH Sec-CH-UA-Platform-Version: " <<
evidence->operator[]("header.Sec-CH-UA-Platform")
= uachPlatform;
evidence->operator[]("header.Sec-CH-UA-Platform-Version")
printResults(results);
deviceId_hintedHub = results->getDeviceId();
delete results;
};
{
evidence->clear();
// Carries out a match for a platform based on device ID.
cout << "\n[---]\n";
cout << "DeviceID: " << deviceId_mobile << " -- Mobile\n";
evidence->operator[]("query.51D_deviceId")
= deviceId_mobile.c_str();
printResults(results);
cout << " [control platform ID: " << deviceId_hintedHub << " -- MediaHub (hinted, no-deviceId)]\n";
delete results;
};
{
evidence->clear();
// Carries out a match for a platform with invalid device ID.
cout << "\n(+)\n";
const char* const deviceId_dummy = "123234-2244-1242-2412";
cout << "DeviceID: " << deviceId_dummy << " -- Dummy\n";
evidence->operator[]("query.51D_deviceId")
= deviceId_dummy;
printResults(results);
cout << " [control platform ID: " << deviceId_hintedHub << " -- MediaHub (hinted, no-deviceId)]\n";
delete results;
};
{
// Carries out a match for a mobile User-Agent with hinted MediaHub DeviceID.
EvidenceDeviceDetection* const evidence2 =
new EvidenceDeviceDetection();
cout << "\n[---]\n";
cout << "Mobile User-Agent: " <<
mobileUserAgent << "\n";
cout << "DeviceID: " << deviceId_hintedHub << " -- MediaHub (hinted)\n";
evidence2->operator[]("header.user-agent")
// case-insensitive
evidence2->operator[]("query.51d_dEVIcEiD")
= deviceId_hintedHub.c_str();
DeviceDetection::Hash::ResultsHash* results = engine->process(evidence2);
printResults(results);
cout << " [control platform ID: " << deviceId_mobile << " -- Mobile (no-deviceId)]\n";
delete results;
delete evidence2;
};
{
evidence->clear();
// Carries out a match for a base 64 encoded GetHighEntropyValue JSON result.
cout << "\n[---]\n";
const char* const ghev_dummy =
"eyJicmFuZHMiOlt7ImJyYW5kIjoiTm90L0EpQnJhbmQiLCJ2ZXJzaW9uIjoiOCJ9LHsiYnJh"
"bmQiOiJDaHJvbWl1bSIsInZlcnNpb24iOiIxMjYifSx7ImJyYW5kIjoiR29vZ2xlIENocm9t"
"ZSIsInZlcnNpb24iOiIxMjYifV0sImZ1bGxWZXJzaW9uTGlzdCI6W3siYnJhbmQiOiJOb3Qv"
"QSlCcmFuZCIsInZlcnNpb24iOiI4LjAuMC4wIn0seyJicmFuZCI6IkNocm9taXVtIiwidmVy"
"c2lvbiI6IjEyNi4wLjY0NzguMTI3In0seyJicmFuZCI6Ikdvb2dsZSBDaHJvbWUiLCJ2ZXJz"
"aW9uIjoiMTI2LjAuNjQ3OC4xMjcifV0sIm1vYmlsZSI6ZmFsc2UsIm1vZGVsIjoiIiwicGxh"
"dGZvcm0iOiJtYWNPUyIsInBsYXRmb3JtVmVyc2lvbiI6IjE0LjUuMCJ9";
cout << "GetHighEntropyValues: " << ghev_dummy << " -- base64 encoded JSON\n";
evidence->operator[]("query.51D_gethighentropyvalues")
= ghev_dummy;
printResults(results);
delete results;
};
{
evidence->clear();
cout <<" \n[---]\n";
const char * const sua = "{\"browsers\":[{\"brand\":\"Chromium\",\"version\":[\"124\",\"0\",\"6367\",\"91\"]},{\"brand\":\"Google Chrome\",\"version\":[\"124\",\"0\",\"6367\",\"91\"]},{\"brand\":\"Not-A.Brand\",\"version\":[\"99\",\"0\",\"0\",\"0\"]}],\"platform\":{\"brand\":\"Windows\",\"version\":[\"14\",\"0\",\"0\"]},\"mobile\":0,\"architecture\":\"x86\",\"source\":2}";
evidence->operator[]("query.51D_structureduseragent") = sua;
cout << "SUA:" << sua << std::endl;
printResults(results);
delete results;
};
// Free the evidence.
delete evidence;
cout << "\n";
}
};
}
}
}
extern "C" void fiftyoneDegreesExampleCPPGettingStartedRun(
ExampleParameters *params) {
// Call the actual function.
DeviceDetection::Hash::ConfigHash* cppConfig =
new DeviceDetection::Hash::ConfigHash(&configHash);
// Ensure special evidence like deviceId and GetHighEntropyValues are
// enabled.
try {
params->dataFilePath, cppConfig);
gettingStarted->run();
delete gettingStarted;
}
catch (const StatusCodeException &e) {
ExampleBase::reportStatus(e.getCode(), params->dataFilePath);
exit(1);
}
}
#ifndef TEST
int main(int argc, char* argv[]) {
if (argc > 1) {
strcpy(dataFilePath, argv[1]);
}
else {
status = fiftyoneDegreesFileGetPath(
dataDir,
dataFileName,
dataFilePath,
sizeof(dataFilePath));
}
if (status != FIFTYONE_DEGREES_STATUS_SUCCESS) {
ExampleBase::reportStatus(status, dataFileName);
fgetc(stdin);
return 1;
}
ExampleParameters params;
params.dataFilePath = dataFilePath;
// run the example
fiftyoneDegreesExampleMemCheck(
¶ms,
fiftyoneDegreesExampleCPPGettingStartedRun);
// Wait for a character to be pressed.
fgetc(stdin);
return 0;
}
#endif
Value< string > getValueAsString(const char *propertyName)
Get a string representation of the value associated with the required property name.
Encapsulates a value returned an instance of ResultsBase for a specified property.
Definition Value.hpp:76
T getValue() const
Gets the value contained in the Value instance.
Definition Value.hpp:131
const char * getNoValueMessage() const
Gets a message explaining why there is no value.
Definition Value.hpp:121
bool hasValue() const
Indicates whether or not a valid value has been returned by the ResultsBase instance.
Definition Value.hpp:102
void setProcessSpecialEvidence(bool process)
Set whether special evidence like getHighEntropyValues, Structured User Agents, or Device Ids,...
C++ class wrapper for the fiftyoneDegreesConfigHash configuration structure.
Definition ConfigHash.hpp:72
Encapsulates the results of a Hash device detection engine's processing.
Definition ResultsHash.hpp:80
string getDeviceId(uint32_t resultIndex) const
Returns the unique device id if the Id property was included in the required list of properties when ...
Base class extended by all Hash examples.
Definition ExampleBase.hpp:58
EngineHash * engine
Hash Engine used for the example.
Definition ExampleBase.hpp:229
ExampleBase(byte *data, long length, DeviceDetection::Hash::ConfigHash *config)
Construct a new instance of the example to be run using the data pointer provided.
static const char * mobileUserAgent
Example mobile User-Agent string.
Definition ExampleBase.hpp:101
static const char * mediaHubUserAgent
Example media hub User-Agent string.
Definition ExampleBase.hpp:113
static void reportStatus(fiftyoneDegreesStatusCode status, const char *fileName)
Reports the status of the data file initialization.
DeviceDetection::Hash::ConfigHash * config
Configuration for the Engine.
Definition ExampleBase.hpp:225
static const char * desktopUserAgent
Example desktop User-Agent string.
Definition ExampleBase.hpp:104
static const char * uachPlatform
Example UACH Platform value.
Definition ExampleBase.hpp:107
static const char * uachPlatformVersion
Example UACH Platform Version value.
Definition ExampleBase.hpp:110
Hash Getting Started Example.
Definition GettingStarted.cpp:127
void printResults(DeviceDetection::Hash::ResultsHash *results)
Check that the value is populated before using the result.
Definition GettingStarted.cpp:139
GettingStarted(string dataFilePath, DeviceDetection::Hash::ConfigHash *config)
Construct a new instance of the example to be run using the data file provided.
Definition GettingStarted.cpp:132
void run()
Run the example.
Definition GettingStarted.cpp:159
#define FIFTYONE_DEGREES_FILE_MAX_PATH
Define the max path length on the target system.
Definition file.h:218
EXTERNAL_VAR fiftyoneDegreesConfigHash fiftyoneDegreesHashDefaultConfig
Default detection configuration.
Definition hash.h:436
fiftyoneDegreesStatusCode
Status returned from the initialisation of a resource.
Definition status.h:81
