Adding Device Data to Proactive Surveys in HappySignals
Extend proactive survey context in HappySignals by adding device data via ServiceNow script includes. Detailed technical steps, best practices, and troubleshooting.
Adding Device Data to Proactive Surveys in HappySignals
Purpose
This article is designed for Proactive IT Experience 2.x and explains how to extend the context data of proactive surveys to include device information (e.g., Laptops and Computers) using the HappyProactiveCustomConfig script and ServiceNow CMDB.
Prerequisites
- Scripted Extension Points are enabled in the HappySignals application
- Access to the relevant asset or CMDB tables in ServiceNow
- IT Experience Administrator or Administrator role
Implementation Steps
1. Identify the Correct Table
- Confirm which table contains your device records. In most cases, this is
alm_asset, but it can vary. - If your organization uses CMDB CI Computer, copy the table name from the URL and replace
alm_assetin the script accordingly.
Performance considerations
- Ensure commonly queried fields, such as
assigned_toandinstall_statusare indexed in your asset table. - If only the most recently assigned device is required, consider limiting the query after ordering results to reduce processing overhead.
2. Add Logic to HappyProactiveCustomConfig
Insert a condition and function to fetch device details and attach them as URL parameters for the survey:
if (obj.survey_id.toString() == "computer") {
var asset = this.__getAssetDetails(obj.user.toString());
if (!gs.nil(asset)) {
for (key in asset) {
conf[key] = asset[key];
}
}
}
Thesurvey_idvalue refers to the proactive survey type.
3. Function to Retrieve Device Details
Update the function based on your table and field names:
__getAssetDetails: function(user) {
var assetDetails = { "devices": 0 };
if (gs.nil(user)) return null;
try {
var assets = new GlideRecord('alm_asset'); // Replace if using CMDB CI Computer
assets.addQuery('model_category.name', 'Computer'); // Adjust if using custom category
assets.addQuery('install_status', '101'); // Use numeric value for "in use"
assets.addQuery('assigned_to', user);
assets.orderByDesc('assigned'); // Ensures latest assigned device is selected
assets.query();
while (assets.next()) {
if (assetDetails.devices == 0) {
assetDetails.pc_type = this.__getFieldValue(assets, 'model_category');
assetDetails.pc_model = this.__getFieldValue(assets, 'model.name');
assetDetails.pc_manuf = this.__getFieldValue(assets, 'model.manufacturer');
assetDetails.pc_os = this.__getFieldValue(assets, 'ci.os');
assetDetails.pc_insdate = this.__getFieldValue(assets, 'install_date', 'time');
assetDetails.pc_age = this.__getAssetAgeRange(assets, 'install_date');
}
assetDetails.devices++;
}
} catch (e) {
gs.error("Error collecting asset details: " + e);
}
return assetDetails;
}
For thepc_age you still need to define the helper function by adding it to the very end of the script:
__getAssetAgeRange: function(asset, dateField) {
if (gs.nil(asset) || !asset.isValid()) {
gs.warn("HappyItExCustomConfig - __getAssetAgeRange: Invalid asset passed, could not determine age range.");
return "";
}
if (gs.nil(dateField) || gs.nil(asset[dateField])) {
gs.warn("HappyItExCustomConfig - __getAssetAgeRange: Invalid date field passed, could not determine age range.");
return "";
}
// key is the range name passed to HappySignals
// value is the cut-off age in years for that range
// DO NOT ADJUST THIS RANGE MAP
var ageRanges = {
"0-2 months": 0.16667,
"2-6 months": 0.5,
"6 months - 1 year": 1,
"1-2 years": 2,
"2-3 years": 3,
"3-4 years": 4,
">4 years": 1000 // this is the last range, it will catch everything older than 4 years
};
var installed = new GlideDateTime(asset[dateField].toString()),
currentDate = new GlideDateTime(),
deviceAgeYears = GlideDateTime.subtract(installed, currentDate).getDayPart() / 365;
for (range in ageRanges) {
if (deviceAgeYears < ageRanges[range]) {
return range; // return the first range that the device age falls into
}
}
return "";
},
Make sure the snippets above come before the line:
type: "HappyProactiveCustomConfig",
Device context fields
The following fields are added dynamically to the survey context:
| Field name | Description |
|---|---|
devices |
Number of active devices assigned to the user |
pc_type |
Device category |
pc_model |
Device model |
pc_manuf |
Manufacturer |
pc_os |
Operating system |
pc_insdate |
Installation date |
pc_age |
Device age |
4. Mobile Device Surveys
Create a similar function for mobile devices:
assets.addQuery('model_category.name', 'Mobile phone');
assets.addQuery('install_status', 'in use'); // or numeric equivalent
Rename fields to avoid duplication:
assetDetails.mobile_type = this.__getFieldValue(assets, 'model_category');
assetDetails.mobile_model = this.__getFieldValue(assets, 'model.name');
``
Best Practices
- Preserve existing logic: Do not remove existing scripts (e.g., Laptop and Computers). Add new ones alongside.
- Use clear field names: Examples:
pc_model,mobile_model. - Ensure data security: Do not include personally identifiable information (PII).
- Test before production: Validate with a test survey.
- Document changes: Add comments in the script and update internal documentation.
Troubleshooting
- Device table mismatch: If
alm_assetdoes not exist, check your CMDB structure. Common alternatives includecmdb_ci_computeror custom asset tables. - Field names differ: Use Show XML or Dictionary in ServiceNow to confirm exact field names (e.g.,
install_status,assigned_to). - Install status values: If “in use” is not recognized, verify numeric codes (commonly
101for active/in use). - Multiple devices per user: The script uses
orderByDesc('assigned')to select the most recently assigned device. - Script errors: Check system logs for
gs.errormessages and confirm that the Scripted Extension Point is active.