By default, feedback context data can be mapped from the incident and requested item tables. With some scripting, it is possible to map data beyond the predefined tables to HappySignals.
An important thing to note is that the table you want to map ideally should extend the “Task” table in ServiceNow. Although, it is technically possible also to map tables that do not extend “Task”, this requires more customisation to the application.
Sending data to HappySignals
Create a HappyCustomConfig script include
Field
|
Value
|
Name
|
HappyCustomConfig
|
API name
|
global.HappyCustomConfig
|
Client callable
|
false
|
Application
|
Global
|
Accessible from
|
All application scopes
|
Active
|
true
|
Description
|
[optional]
|
var HappyCustomConfig = Class.create();
HappyCustomConfig.prototype = {
initialize: function () {
var currentTimeMS = new GlideDateTime().getNumericValue();
this.datestamp = new Date(currentTimeMS).toISOString();
},
/**
* Configure function can override existing data mappings or define mappings for tables not supported by the default configuration logic.
* @param {GlideRecord} obj GlideRecord object that triggered response link creation
* @param {JSON object} conf object that contains configurations made in HappyLinkCreator
* @param {string} tableName name of the table where the GlideRecord object originated
* @returns modified configuration object
*/
Configure: function (obj, conf, tableName) {
/* Available keys on base object described below
Below keys correspond to specific fields on HappySignals cloud
// MANDATORY DETAILS
conf.esm = 'IT'; // top level categorization for the response eg. IT, HR, Security
conf.ticket_type = ''; // type of ticket eg. Request, Incident etc.
conf.category = ''; // survey form key, consult with HappySignals
conf.ticket_number = ''; // ticket number or other identifier
conf.opened_at = ''; // time when the ticket was opened
conf.datestamp = ''; // time for the survey delivery, should be tied to datetime field on the ticket
conf.language = ''; // language code eg. en, fr, es etc.
// BENCHMARK DETAILS
conf.contact_type = '';
conf.country = '';
// END USER DETAILS
conf.employment_started_at = '';
conf.endUserId = ''; // email address of the end-user
// OTHER DETAILS
conf.reassign = '';
conf.assignment_group = '';
conf.priority = '';
conf.location = '';
conf.company = '';
conf.ci = '';
conf.service = '';
conf.secondary_category = '';
conf.tertiary_category = '';
conf.region = '';
conf.vendor = '';
conf.business_stc = '';
conf.time_worked = '';
conf.made_sla = '';
conf.source_object = '';
conf.source_id = '';
*/
// short example of mapping interaction table fields
switch (tableName) {
case 'interaction':
conf.esm = "IT";
conf.ticket_type = "Interaction";
conf.category = "other";
conf.ticket_number = this.__getFieldValue(obj, 'number');
conf.language = this.__getFieldValue(obj, 'opened_for.preferred_language');
conf.datestamp = this.__getFieldValue(obj, 'closed_at', 'time');
conf.contact_type = this.__getFieldValue(obj, 'type');
conf.country = this.__getFieldValue(obj, 'opened_for.location.country');
conf.assignment_group = this.__getFieldValue(obj, 'assignment_group');
break;
}
return conf; // return the configuration object back to HappyLinkCreator to generate the response link
},
/**
* Gets field values and returns them in a format expected by HappySignals
* @param {glideRecordObject} record gliderecord of the object where the field value is retrieved
* @param {string} field field name where the data is retrieved, supports dot-walking to reference fields
* @param {string} returnType in what type the value is returned, options sys_id, value, time, displayValue
* @returns return value from the given field
*/
__getFieldValue: function (record, field, returnType) {
returnType = returnType || 'displayValue'; // set default return type as displayValue if defining argument is not provided
var returnValue = '', //set default return value
elem = record.getElement(field); // get the possibly dot-walked element
if (!gs.nil(elem) && !gs.nil(elem.toString())) {
try {
switch (returnType) {
case 'sys_id':
returnValue = elem.sys_id.toString();
break;
case 'value':
returnValue = elem.toString();
break;
case 'time':
var timeInMS = new GlideDateTime(elem.toString()).getNumericValue();
returnValue = new Date(timeInMS).toISOString(); // time fields need to be formatted to ISO8061 format
break;
default:
returnValue = elem.getDisplayValue();
}
} catch (e) {
gs.info("HappyCustomConfig: mapping for field ({0}) unsuccessfull due to error: {1}", field, e.message);
return ''; // failsafe to prevent other field processing from stopping
}
if (returnValue == undefined || returnValue == null) {
returnValue = '';
}
}
return returnValue;
},
type: 'HappyCustomConfig'
};
${mail_script:happysignals_vote}
Getting the feedback data back to ServiceNow from HappySignals
This guide below applies to application versions 1.5.0 and higher. For lower versions consider updating your application to the latest version.
Modify HappyConstants to configure the integration
HappyConstant is script include that is intended to be modified by customers and is your centralized place for various integration related configurations in the application.
Updating ticket state based on HappySignals Responses
In HappyConstants you can find a constant called "TICKET UPDATE RULES" that determines what happens to a ticket state when a survey response is received by ServiceNow.
Ticket state update rules are defined per table basis and there are default rulesets for incidents, requested items, requests and interactions.
/* TICKET UPDATE RULES */
HappyConstants.ENABLE_WORKNOTE = gs.getProperty('x_pgo_happysignals.enableWorknoteInsertion', 'false') == 'true' ? true : false;
/** HappyConstants.TICKET_STATE_RULES
* Used in "HappySignals Feedback inserted" - business rule
* Defines table based rules to updating record states when feedback record is created to ServiceNow.
* */
HappyConstants.TICKET_STATE_RULES = {
"incident": {
"state_field": "incident_state",
"allowed_states": gs.getProperty('x_pgo_happysignals.incident_statuses', "").split(','),
"set_new_state": gs.getProperty('x_pgo_happysignals.closeIncident', 'false'),
"new_state": "7"
},
"sc_req_item": {
"state_field": "",
"allowed_states": [],
"set_new_state": false,
"new_state": ""
},
"sc_request": {
"state_field": "",
"allowed_states": [],
"set_new_state": false,
"new_state": ""
},
'interaction': {
"state_field": "",
"allowed_states": [],
"set_new_state": false,
"new_state": ""
}
};
/* TICKET UPDATE RULES END */
To update the state for a ticket in your custom table, you will need to add a new ruleset where the object key is the name of your custom table.
Within the ruleset you have four keys that determine what is the field name for state tracking, what are the states that allow updates to happen, whether a new state should be set or not and what is the new state for the ticket.
An example rule set for setting an HR case to "Closed Complete" based on a response can be found below.
'sn_hr_core_case': {
"state_field": "state",
"allowed_states": ["10"], // only "Ready" state allow update to occurr
"set_new_state": true,
"new_state": 3 // setting the state to "Close Complete"
}
If a choice field with integers is used, the allowed_states array elements must still be formatted as string values due to how ServiceNow returns values for the comparison.
Response data enrichment in ServiceNow
Integration from HappySignals back to ServiceNow uses a transform map to enrich the response information with the latest details from the related ticket. This information contains details such as the agent resolving or closing the ticket, the associated assignment groups etc.
The transform map consists of one "onBefore" transform script and multiple "Field Map" definitions, each containing rules for data enrichment. The data enrichment rules are defined in the HappyConstants script.
onBefore Transform Script constants
There are two constants that affect the transform script functionality:
INTEGRATION_TABLES
Defines the list of table names which are used to look up whether a particular ticket can be found in the ServiceNow instance. The integration uses "ticketId", usually the ticket number, returned from the API to make the lookup to. The first table where a match is found is used as the basis for later processing.
/** HappyConstants.INTEGRATION_TABLES
* Used in "HappySignals Feedback Import" -transform map onBefore script
* List of table names that are used to look for records related to feedbacks.
* */
HappyConstants.INTEGRATION_TABLES = ['incident', 'sc_req_item', 'sc_request', 'interaction', 'sn_hr_core_case'];
Lookups are made starting with the first element in the array and stopped once the first match is found. So if you have core tables like "task" or "sn_hr_core_case" in beginning of the array, then these are used instead of potential child tables where the ticket could also be found like "incident" or "sn_hr_core_case_workforce_admin" etc.
LOG_RESPONSE_IMPORTS
Defines if all successful record imports are logged to ServiceNow "System Logs". You should only enable this when troubleshooting issues with the integration.
/** HappyConstants.LOG_RESPONSE_IMPORTS
* Used in "HappySignals Feedback Import" -transform map onBefore script
* If true logs every succesfull response report import
* */
HappyConstants.LOG_RESPONSE_IMPORTS = false;
Field Map constants
There are six constants that affect field map functionalities listed below. Each rule set is defined as table-specific and rules are applied based on the look-up result from the constant INTEGRATION_TABLES.
There are two types of rule sets, reference field population and GlideList population.
- Reference fields pick the first field value that is found while going through an array of field names.
- GlideList population collects field values from multiple different fields and can also look up fields from other associated records.
RELATED_USER_RULES
These rules define who is determined as the Survey Responder. Your resolution/closure email containing HappySignals rating scale should only be delivered to one person associated with the ticket and this rule should follow that definition.
/** HappyConstants.RELATED_USER_RULES
* Used in "HappySignals Feedback Import" - transform map
* Defines table based rules for populating related_user (Survey Responder) field in HappySignals Feedbacks table.
* Gets single value from first match on field array.
* */
HappyConstants.RELATED_USER_RULES = {
'incident': ['caller_id'],
'sc_req_item': ['request.requested_for'],
'sc_request': ['requested_for'],
'interaction': ['opened_for']
};
RESOLVED_BY_USER_RULES
These rules define who is determined as the person resolving or closing the ticket. See an example below for "sc_req_item" picking up a fallback value if the first defined field doesn't hold a value.
/** HappyConstants.RESOLVED_BY_USER_RULES
* Used in "HappySignals Feedback Import" - transform map
* Defines table based rules for populating resolved_by_user (Resolved by User) field in HappySignals Feedbacks table.
* Gets single value from first match on field array.
* */
HappyConstants.RESOLVED_BY_USER_RULES = {
'incident': ['resolved_by'],
'sc_req_item': ['assigned_to', 'request.assigned_to'],
'sc_request': ['assigned_to'],
'interaction': ['assigned_to']
};
CLOSING_ASSIGNMENT_GROUP_RULES
These rules define who is determined as the assignment group resolving or closing the ticket. See an example below for "sc_req_item" picking up a fallback value if the first defined doesn't hold a value.
/** HappyConstants.CLOSING_ASSIGNMENT_GROUP_RULES
* Used in "HappySignals Feedback Import" - transform map
* Defines table based rules for populating closing_assignment_group (Closing Assignment Group) field in HappySignals Feedbacks table.
* Gets single value from first match on field array.
* */
HappyConstants.CLOSING_ASSIGNMENT_GROUP_RULES = {
'incident': ['assignment_group'],
'sc_req_item': ['assignment_group', 'request.assignment_group'],
'sc_request': ['assignment_group'],
'interaction': ['assignment_group']
};
RELATED_USERS_RULES
These rules define who are determined as the agents related to the ticket. Users listed here will have access to the response record in ServiceNow. Multiple users can be collected directly from the ticket and also associated records in other tables.
For example, related agents for Requests are collected from all requested items where the "Request" is referenced and from all tasks where the requested items are referenced as the task parent.
'sc_request': {
'fields': [],
'linkedRecords': {
'sc_req_item': {
'fields': ['assigned_to', 'closed_by'],
'referenceField': 'request',
'linkedRecords': {
'task': {
'fields': ['assigned_to', 'closed_by'],
'referenceField': 'parent'
}
}
}
}
}
Default definitions:
/** HappyConstants.RELATED_USERS_RULES
* Used in "HappySignals Feedback Import" - transform map
* Defines table based rules for populating related_users (Related Agents) field in HappySignals Feedbacks table.
* Gets multiple values from all matching fields on main record and linked records. Supports recursive structure on linkedRecords.
* */
HappyConstants.RELATED_USERS_RULES = {
'incident': {
'fields': ['assigned_to', 'closed_by', 'resolved_by'],
'linkedRecords': {
'task': {
'fields': ['assigned_to', 'closed_by'],
'referenceField': 'parent'
}
}
},
'sc_req_item': {
'fields': ['assigned_to', 'closed_by'],
'linkedRecords': {
'task': {
'fields': ['assigned_to', 'closed_by'],
'referenceField': 'parent'
}
}
},
'sc_request': {
'fields': [],
'linkedRecords': {
'sc_req_item': {
'fields': ['assigned_to', 'closed_by'],
'referenceField': 'request',
'linkedRecords': {
'task': {
'fields': ['assigned_to', 'closed_by'],
'referenceField': 'parent'
}
}
}
}
},
'interaction': {
'fields': ['assigned_to']
}
};
RELATED_ASSIGNMENT_GROUPS_RULES
These rules define what are determined as the assignment groups related to the ticket. Multiple groups can be collected directly from the ticket and also associated records in other tables.
For example, related assignment groups for Requests are collected from all requested items where the parent "Request" is referenced and from all tasks where any of the requested items are referenced as the task parent.
/** HappyConstants.RELATED_ASSIGNMENT_GROUPS_RULES
* Used in "HappySignals Feedback Import" - transform map
* Defines table based rules for populating related_assignment_groups (Related Assignment Groups) field in HappySignals Feedbacks table.
* Gets multiple values from all matching fields on main record and linked records. Supports recursive structure on linkedRecords.
* */
HappyConstants.RELATED_ASSIGNMENT_GROUPS_RULES = {
'incident': {
'fields': ['assignment_group'],
'linkedRecords': {
'task': {
'fields': ['assignment_group'],
'referenceField': 'parent'
}
}
},
'sc_req_item': {
'fields': ['assignment_group'],
'linkedRecords': {
'task': {
'fields': ['assignment_group'],
'referenceField': 'parent'
}
}
},
'sc_request': {
'fields': ['assignment_group'],
'linkedRecords': {
'sc_req_item': {
'fields': ['assignment_group'],
'referenceField': 'request',
'linkedRecords': {
'task': {
'fields': ['assignment_group'],
'referenceField': 'parent'
}
}
}
}
},
'interaction': {
'fields':['assignment_group']
}
};
Showing feedbacks on HappySignals widgets
All feedbacks are displayed in the HappySignals widgets regardless of the table where the related ticket resides.
However you can define table-specific rules for what data is displayed for the responses. To display table-specific fields, you will need to create a new view for the "HappySignals Feedback" record form that determines which fields will be visible on the Agent Feedback widget.
The application comes with four OOB views for Incidents, Requested Items, Request and a default view for any other tables.
To create a new view follow the steps below:
- Navigate to the HappySignals Feedback table and open any record.
- Right-click over the "Form Header" to bring up the context menu.
- In the context menu, navigate to "Configure > Form Layout"
- In the layout editor, open the "View Name" dropdown and select the option for "New..."
- Name your new view as "agent_widget_your_custom_table_name", for example "agent_widget_sn_hr_core_case" and click "OK"
- Select the fields that you want to show in the widget and save your changes once ready
You can change the display title of your view by navigating to table "sys_ui_view" and updating the "Title" field to be something more user friendly.