GlideAjax in ServiceNow Client Scripts

GlideAjax is one of those hidden gems in ServiceNow that lets you bridge the gap between client‑side UI logic and server‑side data processing without a full page reload. While many developers reach for synchronous g_form calls or the older XMLHttpRequest patterns, GlideAjax offers a clean, asynchronous, and secure way to fetch data, run business rules, or even invoke custom logic from a script include. In this article we’ll walk through the entire lifecycle of a GlideAjax call—from crafting a server‑side Script Include, to invoking it from a client script, handling the JSON response, and polishing the implementation with best‑practice tips. By the end, you’ll have a ready‑to‑paste code sample that you can adapt to your own ServiceNow applications.

Understanding GlideAjax: When to Use It in Client Scripts

GlideAjax shines when you need data that isn’t readily available on the form but can be computed on the server without a full reload. Typical scenarios include fetching a list of related records, validating complex business rules, or pulling configuration values that live in a custom table. Because the call runs asynchronously, the user experience stays smooth—no dreaded “Please wait…” dialogs unless you add them deliberately.

Unlike GlideRecord in a client script, which is unavailable due to security restrictions, GlideAjax respects the platform’s ACL model. The request is sent to a Script Include that runs with the credentials of the user executing the client script, so any ACLs you’ve defined still apply. This makes it safe for exposing only the data you intend, and you can further lock down the Script Include with the “Client Callable” flag.

Performance is another reason to prefer GlideAjax. Since the server does the heavy lifting, you avoid shipping large data sets to the browser only to filter them there. The payload is usually a small JSON object, reducing network traffic and processing time on the client. In high‑traffic environments, batching multiple lookups into a single GlideAjax call can dramatically cut the number of round‑trips.

Finally, use GlideAjax when you want to keep your client code lightweight and maintainable. By moving business logic to a Script Include, you centralize the code, making it easier to test, version, and reuse across multiple UI pages, catalog items, or UI actions. This separation of concerns aligns with ServiceNow’s recommended development practices and helps future‑proof your customizations.

Setting Up the Server‑Side Script Include for GlideAjax

Start by creating a new Script Include (System Definition > Script Includes) and give it a meaningful name, such as UserInfoAjax. Check the “Client Callable” box—this tells the platform that the script can be invoked from client scripts via GlideAjax. In the script body, extend AbstractAjaxProcessor to gain access to helper methods like getParameter and write.

var UserInfoAjax = Class.create();
UserInfoAjax.prototype = Object.extendsObject(AbstractAjaxProcessor, {

    // Entry point called from the client
    getUserDetails: function() {
        var sysId = this.getParameter('sysparm_user_id');
        var user = new GlideRecord('sys_user');
        if (user.get(sysId)) {
            var result = {
                name: user.getValue('name'),
                email: user.getValue('email'),
                title: user.getValue('title')
            };
            // Return a JSON string
            return new JSON().encode(result);
        }
        return '';
    },

    // Optional: expose the method name to the client
    isPublic: function() {
        return true;
    }
});

Notice how the method getUserDetails extracts a parameter named sysparm_user_id. GlideAjax automatically prefixes parameters with sysparm_, so the client script must match that naming convention. The method builds a plain JavaScript object, encodes it to JSON, and returns the string. Returning a JSON string is the simplest way to pass structured data back; the client will later parse it with JSON.parse.

If you need multiple functions in the same Script Include, you can expose each one by adding a public method that simply forwards to a private helper. For example, a getUserGroups function could be added alongside getUserDetails. Just remember to keep the public surface small and well‑documented; every additional entry point increases the attack surface, so limit what you expose to only what the client truly needs.

Testing the Script Include is straightforward. Use the “Script” tab in the Script Include form, or open a background script and instantiate the class directly:

var ajax = new UserInfoAjax();
gs.info(ajax.getUserDetails('sys_id_of_user'));

If the JSON output looks correct, you’re ready to wire it up to the client side.

Writing the Client Script: Calling GlideAjax Asynchronously

On the client side, you typically use a UI Policy, UI Script, or Catalog Client Script to trigger the Ajax call. Begin by creating a new Client Script (type “onChange” or “onLoad” depending on your use case) and instantiate a GlideAjax object, passing the name of the Script Include you just created.

function fetchUserInfo(userSysId) {
    var ga = new GlideAjax('UserInfoAjax');
    ga.addParam('sysparm_name', 'getUserDetails'); // method name
    ga.addParam('sysparm_user_id', userSysId);     // our custom param
    ga.getXMLAnswer(function(response) {
        // This callback runs when the server returns
        handleUserInfoResponse(response);
    });
}

The call to addParam('sysparm_name', 'getUserDetails') tells the server which method to execute. The second addParam passes the actual data the server needs—in this case, the sys_id of the user record. The getXMLAnswer method sends the request and registers a callback function to be executed once the response arrives. Because this is asynchronous, the UI remains responsive, and you can show a spinner if you wish.

You can invoke fetchUserInfo from an onChange client script attached to a reference field:

function onChange(control, oldValue, newValue, isLoading) {
    if (isLoading || newValue == '') return;
    fetchUserInfo(newValue);
}

This pattern ensures that every time the user selects a different person, the client script fires, grabs the latest details, and then hands the data off to a response handler. The separation of concerns—fetching vs. processing—keeps the code tidy and easier to debug.

Don’t forget to handle error scenarios. GlideAjax will still invoke the callback even if the server returns an empty string or an error message. Inside the callback, you can check for a falsy response and display a toast or log to the console. This defensive coding prevents silent failures that can confuse end‑users.

Handling the Response: Parsing JSON and Updating UI Elements

When the server returns a JSON string, the client script must convert it into a JavaScript object. The simplest way is JSON.parse, which turns the string into a usable structure. In our example, the response contains name, email, and title fields that we want to populate on the form.

function handleUserInfoResponse(response) {
    if (!response) {
        g_form.showFieldMsg('u_user', 'Unable to retrieve user details.', 'error');
        return;
    }
    var data = JSON.parse(response);
    g_form.setValue('u_name', data.name);
    g_form.setValue('u_email', data.email);
    g_form.setValue('u_title', data.title);
}

Here, g_form.setValue updates the form fields identified by their field names (u_name, u_email, u_title). If any of those fields are read‑only, you may need to use g_form.setReadOnly first or employ a UI macro to display the values. The showFieldMsg call provides immediate feedback if the Ajax call fails, keeping the user informed.

Finally, consider caching results if the same lookup is performed repeatedly during a session. You can store the parsed object in a client‑side variable (or in sessionStorage) and reuse it, reducing the number of server round‑trips and further improving perceived performance.

Best Practices and Common Pitfalls with GlideAjax Calls

One of the most common mistakes is forgetting to mark the Script Include as “Client Callable.” Without that flag, the server will reject the request, and the client will receive an empty response, leaving you with vague error messages. Always double‑check the checkbox and verify that the method name you pass (sysparm_name) matches exactly the public function defined in the Script Include.

Security is another area where developers slip up. Even though GlideAjax respects ACLs, exposing too much data in a single response can inadvertently reveal sensitive information. Use the least‑privilege principle: return only the fields you need, and consider sanitizing values (e.g., stripping HTML or protecting PII). If a Script Include must be used by multiple clients, create separate, narrowly scoped methods rather than a monolithic “getAllData” function.

Performance tuning is often overlooked. Because each GlideAjax call incurs a network round‑trip, batching multiple queries into a single request can dramatically reduce latency. For example, instead of calling getUserDetails and then getUserGroups separately, combine them into one server‑side method that returns a composite JSON object. Also, leverage caching on the client side when appropriate, but be mindful of data freshness—invalidate the cache when underlying records change.

Lastly, handle error handling and debugging gracefully. Use gs.error on the server side to log unexpected conditions, and in the client script, check for empty responses or JSON parsing errors. Adding gs.info statements in the Script Include and console.log in the client callback can dramatically speed up troubleshooting. Remember that GlideAjax runs in the background, so a failure may not be immediately visible to the end user unless you surface it deliberately.

GlideAjax offers a powerful, secure, and performant bridge between client‑side interactions and server‑side logic in ServiceNow. By following the patterns outlined—defining a clean Script Include, invoking it asynchronously from a client script, parsing the JSON response, and adhering to best practices—you can build responsive, maintainable customizations that enhance the user experience without sacrificing security. Happy coding, and may your Ajax calls be swift and bug‑free!