‹ All essays

ServiceNow

Service Catalog Scripting: Record Producers, Variables, Catalog Client Scripts, and Order Guides

How the catalog works internally

When a user submits a catalog item, ServiceNow creates three types of records:

TableRecord TypeWhat it represents
sc_requestRequestThe overall order (REQ0010001). One per submission.
sc_req_itemRequested Item (RITM)One per catalog item ordered (RITM0010001). Contains variable values.
sc_taskCatalog TaskFulfillment work assigned to teams (SCTASK0010001).

Variable values are stored in sc_item_option and linked to the RITM via sc_item_option_mtom.

Reading variable values in scripts

// In a Catalog Item workflow or Business Rule on sc_req_item:
var ritmGr = new GlideRecord('sc_req_item');
ritmGr.get('number', 'RITM0010001');

// Access variables through the variables object
var laptopModel = ritmGr.variables.laptop_model.getDisplayValue();
var justification = ritmGr.variables.justification.toString();

// In a Catalog Item script (server-side):
// 'current' is the RITM record
var model = current.variables.laptop_model;

Record Producers

A Record Producer creates a record on a target table (like incident) through the Service Catalog UI. The user fills out catalog-style variables, and the Record Producer maps them to fields on the target table.

// Record Producer script (runs on submit, server-side)
// 'current' is the target table record (e.g., incident)
// 'producer' has the variable values

current.short_description = producer.description;
current.category = producer.category;
current.priority = producer.urgency_level;

// Set caller to the person who submitted
current.caller_id = gs.getUserID();

When to use Record Producer vs Catalog Item:

  • Record Producer: When the goal is to create a record on an existing table (incident, change_request, etc.) from the catalog. The user sees a catalog form, but the output is a standard record, not a RITM.
  • Catalog Item: When you need the full request lifecycle (Request → RITM → Tasks) with approvals, fulfillment workflows, and catalog-specific tracking.

Variable Sets

A Variable Set is a reusable group of variables shared across multiple catalog items. Instead of creating the same "Delivery Address" fields on 15 different items, create one Variable Set and attach it to all of them.

// Variable sets are just containers — access their variables
// the same way via current.variables.variable_name

Catalog Client Scripts

These are Client Scripts that run specifically on catalog item forms. They have the same event types (onLoad, onChange, onSubmit) but operate on catalog variables instead of table fields.

// Catalog Client Script — onChange
// Variable: 'laptop_model'
function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading) return;

    // Show/hide the 'special_requirements' variable based on model
    if (newValue === 'MacBook Pro 16') {
        g_form.setVisible('special_requirements', true);
        g_form.setMandatory('special_requirements', true);
    } else {
        g_form.setVisible('special_requirements', false);
        g_form.setMandatory('special_requirements', false);
    }
}

// Catalog Client Script — onSubmit
function onSubmit() {
    var model = g_form.getValue('laptop_model');
    var justification = g_form.getValue('justification');

    if (model === 'MacBook Pro 16' && !justification) {
        g_form.addErrorMessage('Justification required for MacBook Pro 16.');
        return false;  // prevent submission
    }
    return true;
}

Catalog UI Policy

Same concept as a regular UI Policy but scoped to catalog variables. Controls visibility, mandatory state, and read-only state of catalog variables without code.

When Laptop Model = "MacBook Pro 16" → make Special Requirements mandatory. Configured entirely through the UI, no JavaScript needed.

Order Guides

An Order Guide bundles multiple catalog items into a single guided ordering experience. The user walks through steps, and at the end, multiple RITMs are created.

Order Guide scripts can pre-populate variables on child items based on selections in earlier steps:

// Order Guide Rule script — maps a variable from the guide to child items
// 'guide_variables' holds the Order Guide level variables
// 'item_variables' holds the current item's variables

item_variables.delivery_location = guide_variables.office_location;
item_variables.cost_center = guide_variables.department_cost_center;

Common traps

  • Catalog Client Scripts vs regular Client Scripts: Catalog Client Scripts only run on catalog forms. Regular Client Scripts on sc_req_item run on the RITM form, not the catalog order form. These are different contexts.
  • Variable names vs labels: In scripts, use the variable name (e.g., laptop_model), not the label ("Laptop Model"). The name is set when you create the variable and cannot contain spaces.
  • Two-step variable access: current.variables.var_name in server-side scripts, g_form.getValue('var_name') in client-side scripts. They look different but access the same data.
  • Multi-row variable sets (MRVS): These store tabular data and are accessed differently — current.variables.mvrs_name.getRowCount() and iterating rows. They do not work like regular variables.