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:
| Table | Record Type | What it represents |
|---|---|---|
sc_request | Request | The overall order (REQ0010001). One per submission. |
sc_req_item | Requested Item (RITM) | One per catalog item ordered (RITM0010001). Contains variable values. |
sc_task | Catalog Task | Fulfillment 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_itemrun 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_namein 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.