logo

NJP

Implementing an E-Signature (Sign Pad) in a ServiceNow Catalog Item and Attaching It to RITM

New article articles in ServiceNow Community · Dec 17, 2025 · article

Overview

In many business processes, approvals or acknowledgements require a user’s signature. While ServiceNow provides attachment capabilities, there is no out-of-the-box e-signature or sign pad feature for Service Catalog items.

In this article, I’ll walk through a practical approach to:

  • Capture a user’s signature using a sign pad (canvas) inside a catalog item
  • Store the signature as Base64 data
  • Convert it into an image attachment on the RITM after submission

This solution works entirely within ServiceNow using Catalog Variables, a Custom Widget, and Flow Designer.


Requirement

  • A catalog item should allow users to draw their signature
  • The captured signature should be attached to the RITM as an image
  • The signature should behave like an e-sign, captured at request time

High-Level Solution Design

  1. Create a Catalog Item
  2. Add variables:
    • A Custom Widget variable (Sign Pad)
    • A hidden variable to store Base64 signature data

1.png

  1. Build a Sign Pad Widget using HTML canvas
  2. Store the signature as Base64 in a hidden variable
  3. Use Flow Designer to:
    • Read the Base64 value
    • Convert it into bytes
    • Attach it to the RITM as a PNG image

Step 1: Catalog Item Variables

Create the following variables in your catalog item:

1. Custom Widget Variable

  • Type: Custom
  • Purpose: Render the Sign Pad UI
  • Widget: Custom Sign Pad Widget (explained below)

2.png

2. Signature Data Variable

  • Type: Multi-line Text
  • Name: signature_data
  • Visibility: Hidden
  • Purpose: Stores Base64 encoded signature image

This hidden variable acts as a temporary data store between the UI and backend processing.


Step 2: Sign Pad Widget – UI (HTML)

The widget uses an HTML <canvas> element where users can draw their signature.

<div class="text-center">
  <canvas id="signature-pad" width="400" height="200"
          style="border:1px solid #ccc; border-radius:8px; cursor:crosshair; touch-action:none;"></canvas>

  <div class="mt-3">
    <button class="btn btn-primary" ng-click="c.clearSignature()">Clear</button>
    <button class="btn btn-success" ng-click="c.attachSignature()">Attach Signature</button>
  </div>
</div>

UI Behavior

  • Users draw directly on the canvas
  • Clear button resets the canvas
  • Attach Signature converts the drawing into Base64

Step 3: Widget Client Script (Controller Logic)

This script handles:

  • Mouse and touch events
  • Drawing logic
  • Converting the canvas to Base64
  • Storing the Base64 value in the hidden catalog variable
api.controller = function($scope) {
    var c = this;
    var canvas, ctx;
    var drawing = false;
    var lastPos = { x: 0, y: 0 };

    c.$onInit = function() {
        setTimeout(function() {
            canvas = document.getElementById('signature-pad');
            if (!canvas) return;

            ctx = canvas.getContext('2d');
            ctx.lineWidth = 2;
            ctx.strokeStyle = '#000';

            canvas.addEventListener('mousedown', startDraw);
            canvas.addEventListener('mousemove', draw);
            canvas.addEventListener('mouseup', endDraw);

            canvas.addEventListener('touchstart', startDraw);
            canvas.addEventListener('touchmove', draw);
            canvas.addEventListener('touchend', endDraw);
        }, 200);
    };

    function getPosition(event) {
        var rect = canvas.getBoundingClientRect();
        if (event.touches && event.touches[0]) {
            return {
                x: event.touches[0].clientX - rect.left,
                y: event.touches[0].clientY - rect.top
            };
        }
        return {
            x: event.clientX - rect.left,
            y: event.clientY - rect.top
        };
    }

    function startDraw(e) {
        drawing = true;
        lastPos = getPosition(e);
    }

    function draw(e) {
        if (!drawing) return;
        e.preventDefault();
        var pos = getPosition(e);
        ctx.beginPath();
        ctx.moveTo(lastPos.x, lastPos.y);
        ctx.lineTo(pos.x, pos.y);
        ctx.stroke();
        lastPos = pos;
    }

    function endDraw() {
        drawing = false;
    }

    c.clearSignature = function() {
        if (ctx) ctx.clearRect(0, 0, canvas.width, canvas.height);
        drawing = false;
        $scope.page.g_form.setValue('signature_data', '');
    };

    c.attachSignature = function() {
        if (!ctx) return alert("Canvas not initialized.");
        var data = canvas.toDataURL('image/png');
        $scope.page.g_form.setValue('signature_data', data);
        alert("Signature captured successfully. It will be attached after submission.");
    };
};

Key Point

The signature is stored as Base64 PNG data in the hidden variable signature_data.


Step 4: Flow Designer – Attachment Flow

After submission, the attachment is handled using Flow Designer.

Flow Overview

  • Trigger: RITM Created
  • Input: Catalog Variables

Step 4.1: Get Catalog Variable Data

  • Retrieve the value of signature_data
  • Retrieve the RITM Sys ID

Step 4.2: Custom Action – Attach Signature

Create a Custom Flow Action with inputs:

  • signature_data (String)
  • record_id (RITM Sys ID)

Action Script

(function execute(inputs, outputs) {

    var signatureData = inputs.signature_data;
    if (!signatureData)
        return;

    var base64Data = signatureData.replace(/^data&colon;image\/png;base64,/, "");
    var decodedBytes = GlideStringUtil.base64DecodeAsBytes(base64Data);

    var gr = new GlideRecord('sc_req_item');
    gr.addQuery('sys_id', inputs.record_id);
    gr.query();

    if (gr.next()) {
        new GlideSysAttachment().write(
            gr,
            "signature.png",
            "image/png",
            decodedBytes
        );
    }

})(inputs, outputs);


Final Result

  • User draws a signature in the catalog item
  • Signature is captured as Base64
  • On submission, Flow Designer:
    • Decodes the Base64 data
    • Creates a PNG file
    • Attaches it directly to the RITM

catalog item 1.pngRITM with attachment.png

This provides a clean and reusable e-signature experience without external plugins.


Key Benefits

  • No third-party integrations required
  • Works in Service Portal
  • Secure and auditable (stored as attachment)
  • Fully configurable using Flow Designer

Conclusion

This approach enables a lightweight yet powerful e-signature capability in ServiceNow Service Catalog. It can be extended further for:

  • Mandatory signature validation
  • Approval-based signing
  • Multiple signers
  • Timestamp and user stamping

If you’re looking to add real-world digital signing use cases to your catalog workflows, this pattern is a solid foundation.

View original source

https://www.servicenow.com/community/developer-articles/implementing-an-e-signature-sign-pad-in-a-servicenow-catalog/ta-p/3451360