…thoughts on ServiceNow and digital transformation


Adding a Visualization to the Overview Section of the Servicenow Service Operations Workspace Landing Page

Our objective is to add an additional visualization that shows all active changes by type to the carousel on the Service Operations Workspace landing page . When clicking on the parts of the donut that represent the types of changes

  • the list below the visualization should filter for the type clicked on,
  • the title should reflect the type of changes filtered for in the list
  • number of records in the grey box should update to the filtered total
  • the Last refreshed on date time should update

The end result should look like the below

Overview of the Solution

  1. Duplicate the Service desk landing page
  2. Create a new visualization and button bare in the carousel
  3. Create a new client script to update the currentVizSelection client state parameter.
  4. Wire the new client script to the visualization click event.
  5. Test drive, the list should be working at this point but not the grid/cards
  6. Create an EVAM definition and put the sys_id of the new definition in the previously created client script.
  7. Modify the SOWIncidentLandingPageUtility script include.
  8. Modify the Service desk manipulate evam data transform script.

Solution Defects

  • Actions in the cards don’t work. Clicking a card will not bring you to the record.
  • The My Work/My Teams work drop down is not taken into account. The new visualization shows all changes regardless of what is selected in this drop down. Update: This defect is remediated here

Duplicate the Service desk landing page SNC variant

First, open UI Builder and go to Service Operations Workspace and then to the home page.

There is only one variant and because this is a ServiceNow page, it is read-only. Before we go any further, take a look at the Overview subpage by clicking Edit Content. Inside the overview subpage, go to the Incidents assigned visualization component and then Events. Notice that there is a mapping for Visualization Clicked — it runs the client script UpdateEvamCardStateVariables.

Now duplicate the variant of the page (not the subpage) so you have a copy you can modify.

In the variant you just created, go to the Overview subpage and to the Incidents assigned visualization component and then to Events just like we did in the original page. Notice that the mapping we saw in the orignal page is not there!

Surprisingly, the darn thing still works though, I’m not sure why this is. I reported a similar phenomenon of disappearing event mappings when duplicating variants to HI and they confirmed this is a defect.

Now change the Order in the conditions on the new variant so that it shows up by default instead of the OOB variant. The OOB is set for 100, so anything below that will do it.

Add Visualization and Bare Button Components

Add another container to the carousel and put a visualization component and a bare button component inside of it. Copy the CSS from any of the other containers in the viz carousel so that it’s the same size

Set up the datasource in the visualization as below.

You’ll notice that the other visualizations (with the exception of unassigned incidents), get their data source and metric dynamically from a client state parameter. Almost all of the parameters for the components in the viz carousel are located in the SowIncidentLandingPageUtilsSNC client script include (sys_ux_client_script_include). For simplicity’s sake, I chose not to mess with this client script include and instead set the parameters directly in the component or in a client script in the subpage.

Rename the id to “change_type_all” and turn off “show border”

Now go to the bare button component and rename the id (and the label if you want). This is important because the id gets picked up in the client script we created.

Create a New Client Script

Go to client scripts in UI builder and add a new one

I named mine updateCurrentVizSelection_new so I could more easily find it in the list, but this isn’t the best name. The other scripts start with a capital letter and don’t have underscores so if this for production, I would be more careful about it 🙂

Paste the below into the new script:

 * @param {params} params
 * @param {api} params.api
 * @param {any} params.event
 * @param {any} params.imports
 * @param {ApiHelpers} params.helpers
function handler({
}) {
    //set up the variables that need to be defined per component
    var table;
    var title;
    var query;
    var evamId;
    //if the view all button for changes is clicked
    if (event.elementId == "change_view_all") {
        table = "change_request";
        title = "All changes";
        query = "active=true";
        evamId = "bca68e6e47456110706003abd36d43eb";//need to update this later
    //if part of the change donut is clicked
    } else if (event.elementId == "changes_type_donut") {
        table = event.payload.params.table;
        title = event.payload.data.elements[0] + " changes";
        query = event.payload.params.query;
        evamId = "bca68e6e47456110706003abd36d43eb"; //need to update this later

    //define the currentVizSelection 
    const currentVizSelection = {
        "table": table,
        "element": "incident_all",
        "title": title,
        "query": query,
        "evamId": evamId,
        "queryForViewAllRecordCount": query,
        "tableForViewAllRecordCount": table
    //set the state
    api.setState("currentVizSelection", currentVizSelection);
    //this is for the last refreshed on datetime
    api.setState('listRefreshRequested', {
        timestamp: new Date().getTime()

Basically what we’re doing here is setting up another way of setting the currentVizSelection client state parameter. The OOB visualizations, use the SowIncidentLandingPageUtilsSNC client script include (and a bunch of other scripts) to store parameters. Again, rather than messing with that, I just create a new client script.

Map the Script to Events in the Components

Now go back to the new visualization we created earlier and map the event to the script we just created.

Do the same for the bare button component:

Test Drive

At this point, the new visualization should now respond to clicks and filter the list below it. Note that it will not update the cards as we need to create an EVAM.

If your list is not getting filtered by the clicking the visualization, you can do some debugging by adding console.log(‘hello i’m running’) or something like that to the client script. Then save, refresh the page, open dev tools in the browser (F12) and bring up the console. Look for your console.log message when clicking the new visualization. If you don’t see it, the event is not mapped to the script correctly.


Next we’re going to create an EVAM definition so that the card view will work.

Go to EVAM Definitions

Then go to the Service desk incident record. Do an insert and stay

Inside the new EVAM definition in the EVAM Datasource M2Ms tab, click Create and Link to create a new datasource

Create the new datasource

Then, back in the EVAM definition, go to EVAM View Config Bundles and click Create and Link

Give the new config bundle a name and click Save. Then do a new EVAM view config. Leave the View Template blank for now.

Create a new EVAM view template by going to View Templates

I used the below for my template, but I didn’t put any effort into it (on the todo list)… you can definitely improve on it. Note that the navigation doesn’t work (also on my todo list).

	"component": "now-card-evam-record",
	"staticValues": {
        "detailLabelOne": {
            "translatable": true,
            "key": "Priority"
        "detailLabelTwo": {
            "translatable": true,
            "key": ""
        "detailLabelThree": {
            "translatable": true,
            "key": "SLA"
        "detailLabelFour": {
            "translatable": true,
            "key": "Assigned to"
    "mappings": {
        "highlightedHeaderLabel": "state",
        "textHeaderLabel": "number",
        "titleLabel": "short_description",
        "subtitle": "sys_updated_on",
        "detailValueOne": "priority",
        "detailValueTwo": "type",
        "detailValueThree": "",
        "detailValueFour": "assigned_to" 
    "actionMappings": {
        "overflowActions": ["reassign"],
        "clickAction": "navigation"

Now go back to the EVAM definition record and get the sys_id. Return to UI Builder to the client script we created earlier and replace the evamId with your sys_id

SOWIncidentLandingPageUtility Script Include

Now go to Script Includes and find the SOWIncidentLandingPageUtility record. We have to add CHART_COLORS for the change_request table as below (I copied the whole CHART_COLORS variable from the SNC script include, probably not necessary.

var SOWIncidentLandingPageUtility = Class.create();
SOWIncidentLandingPageUtility.prototype = Object.extendsObject(SOWIncidentLandingPageUtilitySNC, {
    initialize: function() {
        this.CHART_COLORS = {
            "incident": {
                "state": {
                    '1': 'moderate',
                    '2': 'info',
                    '3': 'warning',
                    '6': 'positive',
                    '7': 'high',
                    '8': 'low'
                "priority": {
                    '1': 'critical',
                    '2': 'high',
                    '3': 'info',
                    '4': 'low',
                    '5': 'positive'
            "sc_task": {
                "state": {
                    '-5': 'warning',
                    '1': 'moderate',
                    '2': 'info',
                    '3': 'positive',
                    '4': 'high',
                    '7': 'low'
			"change_request": {
                "state": {
                    '1': 'moderate',
                    '2': 'info',
                    '3': 'warning',
                    '6': 'positive',
                    '7': 'high',
                    '8': 'low'
                "priority": {
                    '1': 'critical',
                    '2': 'high',
                    '3': 'info',
                    '4': 'low',
                    '5': 'positive'

    type: 'SOWIncidentLandingPageUtility'

Service desk manipulate evam data Data Broker Transform Script

Go to the data broker transform table sys_ux_data_broker_transform and find the record “Service desk manipulate evam data”. Line 60 and line 81 take care of the incident and sc_task tables, insert the below code at line 84 for change_request:

When the EVAM data is returned to the client, there is a data transform script that runs to add the last comment to the subtitle of the card. The table names in this script are hard-coded, so we have to add another few lines for the change_request table.

    if (table === 'change_request') {
        return input.evam_data;

You’ll notice that I’m just returning the input data without transforming. If you want to add the last comment to the subtitle, go ahead and do that here like in the other parts of the script (you could probably even recycle the sc_task if section.