Kaizen 232 - Building a Ticket Escalation Mechanism from Zoho CRM

Kaizen 232 - Building a Ticket Escalation Mechanism from Zoho CRM



Howdy, Tech Wizards!

Picking up the thread from last week, we will continue our Zoho CRM and Zoho Desk integration. 

In Kaizen #231 - Embedding Zoho Desk Tickets in Zoho CRM, we built a Related List widget that displays open Zoho Desk tickets within the Contact detail page. 

Now, let us take it a step further. 

We will enable sales representatives to escalate critical support tickets directly from Zoho CRM.

This controlled escalation mechanism triggers the SLA in Zoho Desk and simultaneously creates a trackable work item in Zoho CRM. The work item captures additional notes from the Sales team, enabling immediate action by the support team. It also allows Sales to monitor escalation progress anytime.

Business Problem

At Zylker, the Sales team works in Zoho CRM to manage customer relationships and track ongoing deals, while the Support team uses Zoho Desk to manage customer issues and service requests. Now the sales representatives have visibility into open support tickets using the widget built in the previous post. However, there is no structured way to escalate tickets from within Zoho CRM.

This leads to:
  1. Delayed escalations, increasing customer frustration.
  2. Lack of accountability when issues slip through the cracks.
  3. No audit trail of internal interventions for compliance and review.
Visibility alone is not enough. Sales teams need an actionable escalation mechanism within CRM.

Solution

We will extend the existing Related List widget by adding an Escalate button to each ticket row. On clicking this button, a confirmation pop-up appears. 

When the user clicks the Confirm button in the pop-up, the ticket status in Zoho Desk is updated to Escalation from Zoho CRM. This status change triggers the associated SLA configured in Zoho Desk.

As part of the SLA automation, the ticket priority can be updated to High, and the ticket owner can be notified. You can also configure additional actions based on your business requirements. If the Support team does not respond within the defined SLA time, the ticket can be automatically escalated to a manager or the escalation team.

After the ticket status is updated, the confirmation pop-up closes and an escalation form appears within the parent widget. This form allows the Sales team to capture additional details such as escalation reason, customer impact, and expected closure date. When the form is submitted, a record is created in a custom module called Escalation Work Items in Zoho CRM.

The Support team accesses only the Escalation Work Items module in Zoho CRM. This module acts as a shared escalation tracker between the Sales and Support teams. Support agents review the escalation details provided by Sales, take the required action in Zoho Desk, and update the escalation record in CRM. This allows the Sales team to track progress and stay informed before their sales call. 

Prerequisites

1. Complete the Related List Widget setup from Kaizen #231 - Embedding Zoho Desk Tickets in Zoho CRM. Ensure the following are already configured:
  1. Related List Widget in CRM
  2. Two-way sync between Zoho CRM and Zoho Desk
  3. Existing Zoho Desk connection
  4. Working widget project
2. Update the existing Zoho Desk connection to include the Desk.tickets.UPDATE scope in addition to the existing Desk.tickets.READ and Desk.contacts.READ scopes.


Refer to the Connections help doc for more information. 

3. Create a custom module named Escalation Work Items in Zoho CRM to store escalation records. 


  1. Go to Zoho CRM > Setup > Customization > Modules and Fields.
  2. Click Create New Module and enter Escalation Work Items as the module name. 
  3. Add the following custom fields:
Fields
Date Type
Contact Name
Lookup
Customer Impact
Multiline
Desk Ticket
URL
Escalation Reason
Multiline
Expected Closure Date
Date Time

Refer to the Customizing Modules help page to learn more about it. 


Make GET Modules Metadata and GET Fields Metadata API calls to retrieve the API names of the required module and its fields.

Store these API names, as they will be used later in the widget implementation.

4. Create a custom ticket status in Zoho Desk to differentiate that the particular ticket is escalated from Zoho CRM. 
  1. Log into Zoho Desk. 
  2. Go to Settings > Customization > Layouts and Fields > Ticket Status and click Add Status.
  3. Fill in the Status Name, Status Type and click Save.


4. Create an SLA in Zoho Desk that triggers when the ticket status changes to Escalation from Zoho CRM.
  1. Go to Settings > Automation > Service Level Agreements and click New SLA
  2. Provide Name and Description to the SLA. 
  3. Choose the trigger condition as Field Update and select the Status field. 
  4. Click Next and proceed configuring the target
  5. Configure the escalation rules, response times, and resolution targets as per your business requirements.


5. Create two new files called escalate-popup.html and escalate-popup.js in the widget project. These files will handle the confirmation dialog UI and button actions. 

This pop-up acts as a sub-widget of the parent Related List widget.

6. Validate and Pack the parent widget with the empty files and upload it to Zoho CRM to register the sub-widget. 
  1. Go to Zoho CRM > Setup > Developer Hub > Widgets and click Create New Widget
  2. Provide the widget details and choose the widget type as Button.
  3. Set the file path of escalate-popup.html as the Index Page and upload the package. 
  4. After saving the widget, navigate to the Widget Details page to find its API name. Store this API name, as it will be required in the parent widget to render the pop-up using the openPopup() method. 

Step-by-Step Implementation

In the existing widget project directory, we will add the escalation functionality.

Step - 1: Add the Escalate Button to the Ticket Table

In the renderTickets function, add an escalate button alongside the view link for each ticket row. On clicking, the button has to call the escalateTicket function that opens a pop-up. 

Step - 2: Create the Escalation Confirmation Pop-up

Add the HTML and CSS for the pop-up in the escalate-popup.html and the button functions in the escalate-popup.js file. 

ZOHO.embeddedApp.on("PageLoad", function(data) {
    console.log("Escalation popup loaded with data:", data);
});
ZOHO.embeddedApp.init();
// Confirm escalation - close popup and return confirmed: true
document.getElementById('confirmBtn').addEventListener('click', function() {
    $Client.close({ confirmed: true });
});
// Cancel escalation - close popup and return confirmed: false
document.getElementById('cancelBtn').addEventListener('click', function() {
    $Client.close({ confirmed: false });
});

Use the $Client.close() in pop-up to return data back to the parent widget. When the user clicks Confirm, it returns { confirmed: true }, and when they click Cancel, it returns { confirmed: false }.

Step - 3: Implement the Escalate Ticket Function

In the escalateTicket function, use the openPopup method to open the escalate-popup.html file and render the confirmation dialog. 

When the user clicks Confirm, call the Zoho Desk Update Ticket API to change the ticket status to Escalation from Zoho CRM. This status change automatically triggers the configured SLA in Zoho Desk.

// Escalate a ticket using openPopup
async function escalateTicket(ticketId, subject) {
    try {
        // Open the escalation confirmation popup widget
        var result = await ZDK.Client.openPopup({
            api_name: 'Zoho_Desk_Pop_Up',
            type: 'widget',
            animation_type: 6,
            header: 'Escalate Ticket',
            bottom: 'center',
            height: '250px',
            width: '400px'
        }, {
            ticketId: ticketId,
            subject: subject
        });
        console.log("Popup result:", result);
        // If user clicked Confirm
        if (result && result.confirmed) {
            ZDK.Client.showLoader('Escalating ticket...');
            // Update ticket status to "Escalation from Zoho CRM" using Desk Update Tickets API
            const updateResponse = await deskZrc.patch('/tickets/' + ticketId, {
                status: 'Escalation From Zoho CRM'
            });
            console.log("Update Ticket Response:", updateResponse);
            ZDK.Client.hideLoader();
            ZDK.Client.showMessage('Ticket escalated successfully');
            // Show escalation details form
            var ticketUrl = 'https://desk.zoho.com/agent/zylkerpvtltd/zylker/tickets/details/' + ticketId;
            renderEscalationForm(ticketId, ticketUrl, subject);
        }
    } catch (error) {
        ZDK.Client.hideLoader();
        console.error('Error escalating ticket:', error);
        ZDK.Client.showAlert('Failed to escalate the ticket. Please try again.', 'Error');
    }

After the ticket status is successfully updated, render an escalation form within the parent widget to capture additional details.

The form should pre-populate the ticket subject and ticket URL as read-only fields. It should also allow the user to enter the customer impact, escalation reason, and expected closure date.

Step - 4: Create an Escalation Entry in Zoho CRM

The Save button should trigger the saveEscalationRecord function. The function validates that all fields are filled and formats the datetime with timezone offset as required by Zoho CRM. The Contact_Name field relates the escalation record to the current Contact using the entityId captured during page load.

With this payload, the function creates a record in the Escalation Work Items module using the Insert Record API via the ZRC POST method

// Save escalation record to Zoho CRM
async function saveEscalationRecord(ticketUrl, ticketSubject) {
    var customerImpact = document.getElementById('customerImpact').value.trim();
    var escalationReason = document.getElementById('escalationReason').value.trim();
    var expectedClosureDate = document.getElementById('expectedClosureDate').value;
    if (!customerImpact || !escalationReason || !expectedClosureDate) {
        ZDK.Client.showAlert('Please fill in all fields before saving.', 'Validation Error');
        return;
    }
    // Format datetime with timezone offset for CRM 
    var dateObj = new Date(expectedClosureDate);
    var tzOffset = -dateObj.getTimezoneOffset();
    var tzSign = tzOffset >= 0 ? '+' : '-';
    var tzHours = String(Math.floor(Math.abs(tzOffset) / 60)).padStart(2, '0');
    var tzMins = String(Math.abs(tzOffset) % 60).padStart(2, '0');
    var closureDate = dateObj.getFullYear() + '-' +
        String(dateObj.getMonth() + 1).padStart(2, '0') + '-' +
        String(dateObj.getDate()).padStart(2, '0') + 'T' +
        String(dateObj.getHours()).padStart(2, '0') + ':' +
        String(dateObj.getMinutes()).padStart(2, '0') + ':' +
        String(dateObj.getSeconds()).padStart(2, '0') +
        tzSign + tzHours + ':' + tzMins;
    var recordData = [{
        "Name": ticketSubject,
        "Customer_Impact": customerImpact,
        "Escalation_Reason": escalationReason,
        "Expected_Closure_Date": closureDate,
        "Desk_Ticket": ticketUrl,
        "Contact_Name": { "id": entityId }
    }];
    try {
        ZDK.Client.showLoader('Saving escalation record...');
        const crmResponse = await zrc.post('/crm/v8/Escalation_Work_Items', {
            data: recordData
        });
        console.log("CRM Insert Response:", crmResponse);
        ZDK.Client.hideLoader();
        ZDK.Client.showMessage('Escalation record created successfully');
        // Go back to tickets list
        await loadTickets();
    } catch (error) {
        ZDK.Client.hideLoader();
        console.error('Error creating escalation record:', error);
        ZDK.Client.showAlert('Failed to create escalation record. Please try again.', 'Error');
    }
}

Step - 5: Validate and Pack the Widget

Follow the steps given in the Widget help page to validate and pack the widget. A complete working code sample is provided as attachment at the end of this post.

Step - 6: Update the Widgets in Zoho CRM

Since we have added new functionality to the widgets, we need to update it in Zoho CRM.
  1. Go to Zoho CRM > Setup > Developer Hub > Widgets.
  2. Locate the existing Related List widget and pop-up widget. 
  3. Click the settings icon and select Edit
  4. Update the package in both the widgets and click Save

Try it Out!

Let us look at the escalation flow from the Contacts detail page in Zoho CRM.



Info
Key Points to Remember
  1. The Desk connection must include Desk.tickets.UPDATE scope in addition to Desk.tickets.READ and Desk.contacts.READ scopes.
  2. The custom module API name Escalation_Work_Items and field API names like Customer_Impact, Escalation_Reason, Expected_Closure_Date, Desk_Ticket, and Contact_Name are organization-specific. Replace them with your actual API names in the saveEscalationRecord function.
  3. The pop-up widget must be registered separately in the Widgets page, and its API name must be used in the openPopup method. Update the api_name parameter in line 229 with your pop-up widget's API name.
  4. Update the Desk URL pattern in lines 182 and 266 with your portal name and company name.
  5. Ensure the SLA in Zoho Desk is configured to trigger when the status changes to Escalation from Zoho CRM.
  6. If you have a large number of contacts or tickets, implement pagination using from and limit parameters as mentioned in the previous Kaizen.
We hope this Kaizen empowers your sales team to take immediate action on critical support issues without leaving Zoho CRM. The combination of visibility and controlled escalation ensures that no customer issue falls through the cracks.

Have questions or suggestions? Drop them in the comments or write to us at support@zohocrm.com.

On to Better Building!

-----------------------------------------------------------------------------------------------------------

Related Reading 

2. Connections - An Overview
3. CRM Customizations - Related Lists
4. CRM APIs - Insert Records API

-----------------------------------------------------------------------------------------------------------
Idea
Previous Kaizen: Embedding Zoho Desk Tickets in Zoho CRM | Kaizen Collection: Directory



      • Sticky Posts

      • Kaizen #198: Using Client Script for Custom Validation in Blueprint

        Nearing 200th Kaizen Post – 1 More to the Big Two-Oh-Oh! Do you have any questions, suggestions, or topics you would like us to cover in future posts? Your insights and suggestions help us shape future content and make this series better for everyone.
      • Kaizen #226: Using ZRC in Client Script

        Hello everyone! Welcome to another week of Kaizen. In today's post, lets see what is ZRC (Zoho Request Client) and how we can use ZRC methods in Client Script to get inputs from a Salesperson and update the Lead status with a single button click. In this
      • Kaizen #222 - Client Script Support for Notes Related List

        Hello everyone! Welcome to another week of Kaizen. The final Kaizen post of the year 2025 is here! With the new Client Script support for the Notes Related List, you can validate, enrich, and manage notes across modules. In this post, we’ll explore how
      • Kaizen #217 - Actions APIs : Tasks

        Welcome to another week of Kaizen! In last week's post we discussed Email Notifications APIs which act as the link between your Workflow automations and you. We have discussed how Zylker Cloud Services uses Email Notifications API in their custom dashboard.
      • Kaizen #216 - Actions APIs : Email Notifications

        Welcome to another week of Kaizen! For the last three weeks, we have been discussing Zylker's workflows. We successfully updated a dormant workflow, built a new one from the ground up and more. But our work is not finished—these automated processes are

        • Recent Topics

        • Zoho Books Create Invoice API

          I am creating zoho invoices via the API.  Now that zoho has released sub-accounts, i'd like to create invoices and link them to sub-accounts within "sales" account.   For example; my chart of accounts looks like this; Sales ->Website Sales    ->Campaign Sales ->Offline Sales However, when I try to pass these accounts to the API, I receive an error that only Bank accounts can be passed with the create invoice.  
        • Multiselect lookup in subform

          It would be SO SO useful if subforms could support a multiselect look up field! Is this in the works??
        • Ability to Set Text Direction for Individual Cells in Zoho Sheet

          Dear Zoho Sheet Team, We hope you are doing well. We would like to request an enhancement in Zoho Sheet that allows users to set the text direction (right-to-left or left-to-right) for individual cells, similar to what is available in Google Sheets. Use
        • Workflows being applied and the Large unwanted popup

          When a workflow is being applied do to an action, then the Agent is left with a large Window asking if they would like the see the changes this workflow did. Is there any way to disable this prompt from appearing?
        • Contact not saved after editing

          Hi. I discovered a couple of problems with Zoho contact. (1) BUG. Contact is not saved after editing. If you edit an existing contact by putting a bracket in one of the fields you get the message "Contact updated successfully" but nothing is saved. All updates (including the other fields) are lost. Steps to reproduce. Go to an existing contact and change the first name to "Robert (Bob)". (2) In the phone number fields you can only save numeric data (0 to 9). This seems an unneccessary restriction.
        • Zoho Mail Android app update: UI revamp

          Hello everyone! We are excited to share that the first phase of the Zoho Mail Android UI revamp is now live. In this update, we have redesigned navigation bar at the bottom to quickly access the Email, Calendar, Contacts, and Settings modules. Also, the
        • Opt-out from mailing list means can't email at all??

          It seems that if a contact unsubscribes from a mailing list the only way to email them is to uncheck the email opt-out box first, then re-check after the email has been sent. I've been through a chat with support and they confirmed this. This seems bizarre.
        • Email Opt Out Question

          Has the problem where if a customer is emailed opt out prevents you sending standard emails? For me this feature is simply to stop any email marketing and should not block people from receiving emails via Zoho mobile, which makes no sense.
        • Search API filter/sort ignores comment-triggered modifiedTime updates

          Summary When a comment is added to a Call or Account, the parent record's modifiedTime is correctly bumped. This bumped value is visible in: GET /api/v1/calls/{id} ✅ GET /api/v1/calls/search without a filter ✅ — the record's response body shows the new
        • Items Landed Cost and Profit?

          Hello, we recently went live with Zoho Inventory, and I have a question about the Landed Cost feature. The FAQ reads: "Tracking the landed cost helps determine the overall cost incurred in procuring the product. This, in turn, helps you to decide the
        • Bank Feeds

          Since Friday my bank feeds wont work. I have refreshed feeds, deactivate and reactivate and nothing is working
        • Show backordered items on packing slip

          Is it possible to show a column on the Packing Slip that shows number of backordered items when a PO is only partially filled? I would also like to see the Backordered column appear on POs after you receive items if you didn't get ALL of the items or partial amounts of items. And lastly, it would be nice to have the option of turning on the Backordered column for invoices if you only invoice for a partial order. -Tom
        • Users I've shared the sheet with cannot use the Custom Functions

          Hi, I have a Zoho Sheet worksheet that I shared to 2 colleagues, giving them full access: In that worksheet, I created a button with a custom Deluge function and it works flawlessly for me: For those I shared the worksheet to, when they click the button,
        • Introducing parent-child ticketing in Zoho Desk [Early access]

          Hello Zoho Desk users! We have introduced the parent-child ticketing system to help customer service teams ensure efficient resolution of issues involving multiple, related tickets. You can now combine repetitive and interconnected tickets into parent-child
        • Newby Questions

          Q1. The top bar of Zoho Books has a "Search in Banking (/) " field. What is the proper use of this text box? - Searching for Amazon for example has no results but there are transactions. - Is the search case sensitive? - Are regular expressions allowed?
        • Add Custom Fields only in Customer module and not on supplier module!? Is not there a way to do that!?

          I am trying to create custom fields on clients module but it also gets created on suppliers module; which of course does not make sense at all as a lot of custom fields are client or supplier specific but never both. I am missing something? This seems
        • Inventory "Bulk Actions" button - add more fields to "Bulk Update > Select a field"

          Can we not get a lot more actions that are commonly used by customers into the "More Actions" button on the Inventory list? More fields listed in the Bulk Update > Select A Field? Possible Bulk update Fields Preferred Supplier ( to quickly move items
        • Using Email Triggers on Zoho Flow

          Hello, I'm sending the email to create the variables as this article says: https://help.zoho.com/portal/en/kb/flow/user-guide/create-a-flow/articles/email-trigger#How_email_trigger_works But the collection of the variables only seems to work when the
        • Zoho Bookings - Provide Appointment System ID in Zoho Flow Variable

          Hi Bookings Team, It would be great if you could provide the system record ID for appointments as a variable in Zoho Flow trigger outputs and Fetch Appointments action. This would allow us to create a dymanic URL which can be clicked by a staff user to
        • Tip #7: Customize the appointment confirmation page

          A confirmation page plays a crucial role in creating the first impression, as that's where customers land when booking with you. It shows your brand identity, engages your audience, and drives more conversions. Yet, this section is often overlooked when
        • WhatsApp Calling Integration via Zoho Desk

          Dear Zoho Desk Team, I would like to request a feature that allows users to call WhatsApp numbers directly via Zoho Desk. This integration would enable sending and receiving calls to and from WhatsApp numbers over the internet, without the need for traditional
        • Show backordered items on packing slip

          We send out a lot of large orders, and often there are one or two things backordered. How can I fix the packing slips to show quantity ordered  & quantity packed There should also be the ability to "ship" 0 of an item so the receiver knows that things
        • How do you create an event/meeting in a different time zone?

          Does anyone know how do you create an event/meeting in a different time zone? 
        • Deluge Learning Series – Mastering file handling in Deluge | April 2026

          The Deluge Learning Series is conducted on the fourth thursday of every month. In each session, we discuss built-in functions and statements in Deluge and demonstrate how they are used across different Zoho products. With practical examples and real-world
        • Multi-currency and Products

          One of the main reasons I have gone down the Zoho route is because I need multi-currency support. However, I find that products can only be priced in the home currency, We sell to the US and UK. However, we maintain different price lists for each. There
        • Editing recurring tasks

          Hi there, I use recurring annual tasks quite often but sometimes I have a contact leave an organization so I want to re-assign that annual task to a new contact. When I go into the task to change the contact it only does so for the current year. Future
        • Cross Module Filtering – Use Fields from Lookup modules in Custom Views criteria and Advanced Filters

          Hello everyone, Zoho CRM now enables you to achieve deeper filtering of records in a module, using fields of a lookup, thereby enhancing your data management experience manifold. This filtering based on lookup module fields is now available in advanced
        • On Duty Requests - Zoho People Data

          Hello Team, We are currently using the On Duty Form to record Work From Home (WFH) requests in our organization. However, we are facing an issue where pending On Duty requests are not appearing in the Attendance Module. For example, if I submit On Duty
        • Business Day Logic Update: More Accurate Scheduling for Your Workflows

          Hello everyone, We’re improving how business-day calculations work in workflows, especially when triggers happen on weekends. This update ensures that offsets like +0, +1, and +2 business days behave exactly as intended, giving you clearer and more predictable
        • Styling for Subform Fields using client script

          Currently we can add styles to list and detail page for fields using .addstyle in the Client Script But that is missing for fields of Subform We would really like the feature to addstyle for subforms in the detail page Can you please consider adding it,
        • Zoho Commerce -

          Zoho Commerce currently only allows merchants to define the United Kingdom as a single shipping zone, which creates a significant issue for businesses operating between the EU and the UK. Under the Northern Ireland Protocol, Northern Ireland follows EU
        • Add a way to connect Log360 Cloud logs with Zoho analytics

          Hi, Several month ago Log360 Cloud was added to zoho one - and this is great. But as far as I see there is no prebuilt way to connect Zoho analytics to the logs we have in Log360 Cloud. Please add a prebuilt connection like we have for so many other zoho
        • IP flagged as abusive

          I'm getting the error that 136.143.188.15 is listed as abusive. I've checked with mxtoolbox.com and it is indeed in the list
        • date & datetime client script getInput types

          Please add date & datetime as available types for the getInput client script function. https://www.zohocrm.dev/explore/client-script/clientapi/Client#getInput
        • Approval Workflow Not Triggering When Status Updated via Custom Button

          Hi Team, I’m facing an issue with an approval workflow in my application. I have a workflow that updates a record’s Status field from “Pending” to “Waiting for Approval.” I have configured an Approval Workflow with the condition: Status = "Waiting for
        • Automate the file import step

          Hello everyone, I have a Sales - 'Account' category, and currently import the file to update it as follows: Import Accounts - From File - Update existing Accounts only - select and match the field the CRM. Since we have been using Microsoft 365 SharePoint.
        • Data Import

          Hello Latha, Is there any option to enable data import option in Equipment module? Best regards, Chethiya.
        • Unable to Access /crm/v7/taxes – OAuth Scope Mismatch in Zoho CRM API

          I am currently integrating Zoho CRM (v7 API) with our system and I need clarification regarding the Taxes API and OAuth scopes. Context: We are creating Quotes via the API (/crm/v7/Quotes) Each quote contains line items with taxes (e.g., TVA 19%, 10%,
        • Email from CRM being Blocked or Marked as Spam by Google (and maybe more)

          In the past 24 hours we’ve noticed that emails sent via Zoho CRM are being blocked or flagged as phishing, particularly by Google. The issue seems to occur specifically when emails contain links. URLs like www.domain.com or www.example.com are automatically
        • Marketing Tip #29: Make it easier to shop by grouping products into collections

          A well-organized store helps customers find what they want faster, which directly improves conversions. When products are grouped into clear categories or collections, shoppers don’t have to scroll endlessly or search manually. It also makes your store
        • Next Page