ServiceNow – Adding an Animated VIP Icon

I wanted to find a method that would make an incident stand out if it was logged for a VIP user. There is a field decoration (I believe its out of the box) that shows like this:

But I felt that we could get a bit more “pop”. I wanted the engineer to have visibility that this was a VIP incident the entire time they were looking at the record. For that reason I created this (with some help from ChatGPT).

Utilising a client script, I was able to display an animated VIP icon that shows no matter where the engineer is on the form. It looks like this. The image is also pulsing, but I can’t show that in a screenshot so you’ll have to trust me!

I downloaded a VIP icon that I liked the look of. Personally I was a fan of this one https://www.flaticon.com/free-icon/vip_3791579.

Next, you need to add it to the image library in ServiceNow. Open “Images” under “System UI”. Click “New” and upload your image. Name the image “vip_flash.png”. It should look like this when done:

Next, we need to create a client script that will utilise it. Open “Client Scripts” under “System Definition”. Click “New” and configure your client script as follows (you can adjust whatever you need to, I’m focusing on Incident for this one):

NameFlash field – VIP
DescriptionShow an animated VIP popup on the incident form.
TableIncident
UI TypeDesktop
TypeonLoad
Isolate ScriptFalse

Then for the script, add this. Effectively it uses g_form.getReference to see if the user is a VIP. If the user is, create an image element, place it and animate it. It also has a function to get the header hight values; this is to make sure it fits OK.

function onLoad() {
    // Get the reference of the caller_id field
    g_form.getReference('caller_id', function(caller) {
        // Check if the caller is a VIP
        // Double quote to convert to boolean
        if (caller.vip == "true") {
            createVIPAnimation();
        }
    });

    // Setup the onresize event handler
    window.onresize = function() {
        adjustVIPPosition();
    };
}

function createVIPAnimation() {
    // Create an image element to display the VIP image
    var vipImage = document.createElement('img');
    vipImage.src = 'vip_flash.png';
    vipImage.style.position = 'fixed';
    vipImage.style.right = '70px'; // Adjusted to position it on the right
    vipImage.style.width = '50px'; // Set the initial width to be small
    vipImage.style.height = '50px'; // Set the initial height to be small
    vipImage.style.zIndex = '10000';
    vipImage.style.animation = 'vipAnimation 2s infinite';
    vipImage.className = 'vipImage'; // Add a class name to the VIP image for easy selection later

    // Get the height of the header bar dynamically
    var headerHeight = getHeaderHeight();

    // Adjust the top property based on the header bar height
    vipImage.style.top = (headerHeight + 10) + 'px'; // Adding 10px margin to position it below the header

    document.body.appendChild(vipImage);

    // Create style element to hold the keyframes for the animation
    var styleElement = document.createElement('style');
    styleElement.type = 'text/css';
    styleElement.innerHTML = '@keyframes vipAnimation {' + 
                                '0% {' + 
                                    'transform: scale(1);' + 
                                '}' +
                                '50% {' +
                                    'transform: scale(1.1);' + 
                                '}' +
                                '100% {' +
                                    'transform: scale(1);' +
                                '}' +
                            '}';

    document.head.appendChild(styleElement);
}

function getHeaderHeight() {
    var tableName = g_form.getTableName();
    var headerId = tableName + '.form_header';
    var header = document.getElementById(headerId);

    return header ? header.offsetHeight : 0;
}

function adjustVIPPosition() {
    var header = document.getElementById(g_form.getTableName() + '.form_header');
    if (header) {
        var headerRect = header.getBoundingClientRect();
        var vipImage = document.querySelector('.vipImage');
        if (vipImage) {
            vipImage.style.top = (headerRect.bottom + 10) + 'px'; // 10px below the current bottom of the header
        }
    }
}