Server Scripting · Lesson 2.4
Script Includes in ServiceNow: write it once, call it anywhere
- Script Includes
- Business Rules
Why Script Includes exist
Say three Business Rules all need to know how many open Critical incidents there are. The quick way is to paste the same ten lines of counting code into all three. It works, until someone spots a bug in it. Now there are three copies to fix, and on a real instance there is always one copy nobody remembers.
A Script Include solves this by giving the logic a home and a name. The three rules each call it in one line. The bug gets fixed once, in one place, and every caller is fixed at the same time. The rules also become shorter and easier to read: a line like countOtherOpenCritical() says what it does without making you read how.
Finding and creating Script Includes
In your PDI (Personal Developer Instance)A free ServiceNow instance you get from developer.servicenow.com to practise on safely.Learn more , open System Definition > Script Includes. Like Business Rules, the list already holds hundreds that ServiceNow ships with, and ServiceNow’s own code calls them constantly. Select New to create your own. These are the fields on the form:
| Field | What it means |
|---|---|
| Name | The name other scripts use to call it. ServiceNow finds the Script Include by this name, so it must match the name in the script exactly |
| API Name | Filled in for you: the scope plus the name, such as global.CriticalIncidentUtils. Scripts in other application scopes use this full name |
| Application | The application scope it belongs to, such as Global |
| Accessible from | This application scope only, or All application scopes if other applications should be able to call it |
| Glide AJAX enabled | Lets code in the browser call it through GlideAjax. Leave it unticked unless a Client Script really needs it |
| Mobile callable and Sandbox enabled | Allow calls from the mobile app and from sandboxed scripts. Leave them unticked for now |
| Active | Whether the Script Include can be used at all |
| Script | Your code. ServiceNow fills in a starting template as soon as you type the name |
The template, line by line
When you type a name such as CriticalIncidentUtils, the Script field fills itself in with this:
var CriticalIncidentUtils = Class.create();
CriticalIncidentUtils.prototype = {
initialize: function() {
},
type: 'CriticalIncidentUtils'
};
It looks intimidating, but each line has a simple job:
Class.create()makes a new, empty class: a blueprint you can create objects from. The variable name must be the same as the Name field.prototypeis the list of everything objects made from this blueprint can do. Your functions go inside these curly brackets.initializeruns once, every time someone creates a new object withnew. Leave it empty unless every function needs the same setup.typeis a label used by the platform. Leave it as the Script Include’s name.
You add your own functions between initialize and type, separated by commas:
var CriticalIncidentUtils = Class.create();
CriticalIncidentUtils.prototype = {
initialize: function() {},
countOtherOpenCritical: function(excludeSysId) {
// ... the counting code goes here ...
return 0;
},
type: 'CriticalIncidentUtils'
};
Calling it from a Business Rule
To use a Script Include, create an object from it with new, then call a function on that object:
var others = new CriticalIncidentUtils().countOtherOpenCritical(current.getUniqueValue());
Read it from left to right: make a new CriticalIncidentUtils object, call its countOtherOpenCritical function with the incident’s sys_idThe unique 32-character ID every record in ServiceNow has. It never changes, even if every other field does.Learn more , and store what it returns in others. Press Play to follow that one line from the rule into the Script Include and back.
Step 1 of 5 · Rule runs
The Business Rule reaches the call
INC0010061 becomes 1 - Critical and is saved, so the "Warn about Critical overload" Business Rule runs. Its script has one interesting line: it needs a number it does not calculate itself.
var others = new CriticalIncidentUtils().countOtherOpenCritical(current.getUniqueValue());- Running now
- Business Rule script
- Script Include loaded
- No
- Object created
- No
- Value of others
- (not set yet)
Step 2 of 5 · Find it
ServiceNow finds the Script Include by name
The name CriticalIncidentUtils is not defined anywhere in the rule. ServiceNow looks for an active Script Include whose Name field is exactly CriticalIncidentUtils, and loads its script. Script Includes are only loaded when something actually asks for them.
- Running now
- Loading Script Include
- Script Include loaded
- Yes: CriticalIncidentUtils
- Object created
- No
- Value of others
- (not set yet)
Step 3 of 5 · new
"new" creates an object and runs initialize
new CriticalIncidentUtils() makes a fresh object from the Script Include and runs its initialize function once. Ours is empty, but this is where you would set up anything every function needs.
initialize: function() {},- Running now
- initialize()
- Script Include loaded
- Yes: CriticalIncidentUtils
- Object created
- Yes
- Value of others
- (not set yet)
Step 4 of 5 · Function
The function does the work
countOtherOpenCritical runs with the incident's sys_id as its argument. It queries the database and counts the other active Critical incidents. The Business Rule does not need to know how; it only needs the answer.
countOtherOpenCritical: function(excludeSysId) { // ... GlideAggregate query ... return parseInt(ga.getAggregate('COUNT'), 10); }- Running now
- countOtherOpenCritical(sys_id)
- Script Include loaded
- Yes: CriticalIncidentUtils
- Object created
- Yes
- Value of others
- (being calculated)
Step 5 of 5 · Return
The answer comes back to the rule
The function returns 3, and that value lands in the variable others in the Business Rule, which writes its work note. Tomorrow a scheduled job or a UI Action could call the very same function and get the same, correct answer.
- Running now
- Business Rule script (again)
- Script Include loaded
- Yes: CriticalIncidentUtils
- Object created
- Yes
- Value of others
- 3
There is also a simpler kind of Script Include that holds just one function and no class. Its Name is the function’s name, and you call it directly, such as getUserManager(userId), without new. You will see both kinds on real instances. The class kind is more common, because related functions can live together under one name.
See it in your instance
You can call a Script Include without building a Business Rule first, using Scripts - Background, a page where admins run a piece of server script once.
- In your PDI, open System Definition > Script Includes and select New.
- Set Name to
GlideNestDemoUtils, leave Glide AJAX enabled unticked, and replace the script with:
var GlideNestDemoUtils = Class.create();
GlideNestDemoUtils.prototype = {
initialize: function() {},
greet: function(name) {
return 'Hello, ' + name + '! Script Includes are working.';
},
type: 'GlideNestDemoUtils'
};
- Select Submit.
- Open System Definition > Scripts - Background, paste
gs.info(new GlideNestDemoUtils().greet('Priya'));and select Run script. The output shows your greeting. - Now change the Name field to something else, save, and run the same line again. Read the error, then change the Name back. Delete the Script Include when you are done.
Practice: Script Include, or keep it in the rule?
Put logic in a Script Include when more than one place needs it, or when it is a real calculation worth naming. Keep it in the Business Rule when it is short and only that rule will ever use it.
Working out the business days between two dates, needed by two Business Rules and a scheduled job.
Answer: Script Include. Three callers, one calculation. Write it once as a function and call it from all three.
Showing the message "Please attach a screenshot" on save, only for one specific rule.
Answer: Keep it in the rule. One line, one place, nothing to reuse. Moving it into a Script Include would only add a file to look through.
Finding the manager of a user, something many rules, flows and UI Actions on different tables need.
Answer: Script Include. A small helper used everywhere is the classic Script Include. Fix a bug in it once and every caller benefits.
A Client Script that needs a value only the server can look up, such as whether the caller has open incidents.
Answer: Script Include. The browser reaches server code through GlideAjax, which calls a Script Include with Glide AJAX enabled ticked. You will build one in the Client and Server module.
Setting the assignment group to Network when the category is Network, in one before rule.
Answer: Keep it in the rule. A simple, rule-specific default. A filter condition plus two lines of script is perfectly clear on its own.
Counting the other open Critical incidents, as in this module's challenge.
Answer: Script Include. A named calculation that other places will want too: a dashboard widget, a scheduled report or a UI Action.
Firing the event "incident.resolved.custom" from an after rule when an incident is resolved.
Answer: Keep it in the rule. A single gs.eventQueue call that belongs to this one rule. There is nothing to share.
Validating that a phone number is in the right format, needed on the User, Location and Company tables.
Answer: Script Include. The same check on three tables. One function means one place to fix when the format rules change.
What’s next
You can now create a Script Include, add functions to it, and call it from a Business Rule. In the next lesson, GlideAggregate, you will write the kind of logic that belongs inside one: counting and totalling records the fast way, by asking the database for the answer instead of loading every record.
Quick check
A Script Include's Name field says 'IncidentHelper', and its script starts with 'var IncidentUtils = Class.create();'. A Business Rule calls new IncidentUtils().doSomething(). What happens?
Show answer
It fails: IncidentUtils is not defined.
ServiceNow loads a Script Include by its Name field. Nothing is named IncidentUtils, so the class is never loaded and the call fails. Rename the Script Include, or the variable and type, so that all three match exactly.
Was this lesson helpful?
Thanks! Glad it helped. 🙌
Thank you. We will use this to improve the lesson.
Spotted a mistake, or a step that looks different in your instance?