Kaizen #187 - Building a Timer and Worklog Widget (Part 1)

Kaizen #187 - Building a Timer and Worklog Widget (Part 1)



Howdy Tech Wizards!

Welcome back to a fresh week of Kaizen! 

This time, we are diving into a two-part series where you will learn how to build a Timer and Worklog Widget for Zoho CRM. This widget helps track active work time and log multitasking sessions using Zoho CRM APIs, Client Script, Functions, and Workflows.

Why It Matters?

Zoho CRM effectively captures stage/status transitions, like tracking when a case moves from Open to In Progress or On Hold. However, in dynamic work environments, employees juggle multiple work items and engage in impromptu tasks or conversations. 

Let’s take the On Hold status as an example. 

While it can be used to indicate pauses in progress, it does not always align with real-world workflows. Consider these scenarios:

Not all interruptions justify a status change 

Moving the case to On Hold for every minor detour (to clarify something with a colleague or respond to another emergency work item) would be impractical and could lead to under reporting actual work hours. Over time, this untracked effort adds up, creating a gap in visibility.

Frequent status changes may dilute their meaning 

In many teams, On Hold signifies a legitimate blocker like waiting on customer input or an external dependency. Using it frequently to reflect quick shifts in attention could compromise that clarity. 

A timer widget solves this by:
  • Capturing hands-on work items.
  • Logging context switches (unrelated tasks) with descriptive entries.
  • Feeding structured entries into a custom module for reporting and subform sync.

Business Scenario: IT Service Desk & Ticket Resolution

A tech support team uses the Cases module to resolve customer issues. Some tickets are straightforward; others require follow-ups, escalations, or cross-team coordination. While CRM timestamps (like stage transitions or picklist tracking) track when changes happen, they do not reflect how long someone actively worked on a case.

This Timer Widget can be the ultimate solution to track down the active time spent on each case through out the day.

What are we Building?

By the end of this two-part guide, you will know how to:
  • Build a timer widget to track time per task or any CRM record.
  • Log work sessions into a custom module every time the timer is started/stopped.
  • Automatically populate a subform in the corresponding record module using workflows and Deluge functions.
  • Leverage the Reports module to analyze work patterns, SLA adherence, and productivity trends.
 In Part I, we will focus on:
-> Building and configuring the Timer Widget.
-> Capturing each timed session as a record in a custom module.

Prerequisites

1. Create a Custom Module

Create a custom module named Timer Entries to log work details and generate reports from the Reports module. A new record will be added to this module each time a timer is started.

Set up the following custom fields in the Timer Entries module:

Custom Fields
Data Type
Start Time
DateTime
End Time
DateTime
Total Duration (in mins.)
Formula 
DateBetween(${Timer Entries.Start Time},${Timer Entries.End Time},'Minutes')
Related to Case
Lookup to Cases module
Work Description
Multi Line


2. Add a custom picklist option

Add a custom picklist option called In Progress to the Status picklist field in the Cases module for precisely identifying the status of the cases. 

Follow this Add/Remove Picklist Values help section for more details. 

3. Setup Custom Views for Contextual Filtering

To streamline the widget experience and ensure users only see relevant records to associate while tracking time, set up two smart custom views—one in the Cases module and another in the Timer Entries module. 

Active Cases View (Cases Module)

Create a custom view in the Cases module to list only the active tickets the logged-in user is working on. Use the following criteria tips:
  • Use the Status field to filter records with values like In Progress, On Hold, or Escalated.
  • Use the Case Owner field to show records that are assigned only to the currently logged-in user.
This view powers the drop-down inside the widget where users select the case they want to start the timer for.
Active Timers View (Timer Entries Module)

Set up a second custom view in the Timer Entries module to track entries where the timer has been started but not yet stopped. These represent active timers. Use the following logic for criteria:
  • The End Time field is empty (i.e., timer still running).
  • Timer Entry owner field matches the logged-in user.
This view is used internally by the widget to detect if a timer is already running and update the same entry once the timer is stopped.
Follow the Managing List View help page and use the specifications shown in the following image.

Building the Timer Widget 

Step -1: Review Basics

Refer to our earlier Kaizen on CLI Installation, Creating a Widget Project, and Internal hosting of the same.

Step 2 - Develop the Widget

After initializing your widget project using CLI, implement the timer logic:

Fetching Active Cases

On page load, the populateRecordsDropdown function initiates a Get Records API call to the Cases module, using the Active Cases custom view ID. This fetches all active case records assigned to the logged-in user. 

These records are then listed in a dropdown, allowing users to quickly select the relevant case they are about to work on.

async function populateRecordsDropdown() {
            const recordsDropdown = document.getElementById("moduleRecords");
            recordsDropdown.innerHTML = ""; 

            try {
                const recordsResponse = await ZOHO.CRM.API.getAllRecords({
                    Entity: casesModule,
                    cvid: casesCVID,
                    per_page: 10
                });

                if (recordsResponse.data && recordsResponse.data.length > 0) {
                    recordsResponse.data.forEach(record => {
                        const option = document.createElement("option");
                        option.value = record.id;
                        option.textContent = record.Subject || "Unnamed Record"; 
                        recordsDropdown.appendChild(option);
                    });
                } else {
                    const placeholderOption = document.createElement("option");
                    placeholderOption.value = "";
                    placeholderOption.textContent = "No records found";
                    placeholderOption.disabled = true;
                    placeholderOption.selected = true;
                    recordsDropdown.appendChild(placeholderOption);
                }
            } catch (error) {
                console.error("Error fetching records:", error);
            }
        }

Starting the Timer and Creating an Entry

Once the user starts the timer, The createRecord function triggers a Create Record API call to log the session in the Timer Entries custom module. The record captures the start time and the related case and description (if provided).

Even if no details are entered or case is selected, a timer entry is still created with the start time. This ensures that spontaneous work sessions are tracked and not lost.

async function createRecord(startTime) {
            try {
                const workDescription = document.getElementById("workDescription").value;
                const selectedRecordId = document.getElementById("moduleRecords").value;
                const selectedRecordText = document.getElementById("moduleRecords").options[
                    document.getElementById("moduleRecords").selectedIndex
                ].text;

                const data = {
                    Start_Time: startTime,
                    Owner: currentUserId,
                    Work_Description: workDescription,
                    Related_to_Case: selectedRecordId, 
                    Name: selectedRecordText 
                };

                const response = await ZOHO.CRM.API.insertRecord({
                    Entity: timerModule,
                    APIData: data
                });

                console.log("Start time recorded successfully");
            } catch (error) {
                console.error("Error creating record:", error);
            }
        }


Stopping the Timer and Updating the Entry

When the timer is stopped, the widget uses the Active Timer Entry custom view to locate the most recent Timer Entry record created by the logged-in user that does not have an end time. 

The updateRecord is then triggered to update that active entry using the Update Record API call. It updates the End time of the session and the related case, descriptions, if it was not already provided when the timer was started.

async function updateRecord(endTime) {
            try {
                const workDescription = document.getElementById("workDescription").value;
                const selectedRecordId = document.getElementById("moduleRecords").value;

                const response = await ZOHO.CRM.API.getAllRecords({
                    Entity: timerModule,
                    cvid: timerEntriesCVID,
                    per_page: 1
                });

                const latestRecord = response.data[0];
                if (latestRecord) {
                    const recordId = latestRecord.id;
                    const data = {
                        id: recordId,
                        End_Time: endTime,
                        Work_Description: workDescription,
                        Related_to_Case: selectedRecordId 
                    };

                    await ZOHO.CRM.API.updateRecord({
                        Entity: timerModule,
                        APIData: data,
                        RecordID: recordId
                    });
                    console.log("End time updated successfully");
                }
            } catch (error) {
                console.error("Error updating record:", error);
            }
        }

Step 3 - Validate and Pack the Widget

  • Follow the steps given in the Widget help page to validate and package the widget.
  • Go to Zoho CRM > Setup > Developer Hub > Widgets and click Create New Widget.
  • Fill in the required details as shown in this image and ensure to select Button as the widget type.

Step 4 - Associate it with Flyout

  • Go to Setup > Developer Space > Client Script. Click New Script.
  • Enter a name and description for the script. Choose Command type in Category

  • Create a Flyout and render a widget within it using its details like the API name of the widget, title, size, and animation type. You can get the Widget API name from the widget's detail page. 
let allowedUserEmails = [];
allowedUserEmails.push('user1_email_address');
allowedUserEmails.push('user2_email_address');
allowedUserEmails.push('user3_email_address');
let currentUserEmail = $Crm.user.email;
if (allowedUserEmails.indexOf(currentUserEmail) == -1) {
    ZDK.Client.showMessage('Command access resticted', { type: 'error' });
    return false;
}
ZDK.Client.createFlyout('myFlyout', {header: 'Timer', animation_type: 4, height: '600px', width: '500px', top: '10px', left: '10px', bottom: '10px', right: '10px' });
ZDK.Client.getFlyout('myFlyout').open({ api_name: 'Timer', type: 'widget' });
return true;

Refer to Creating a Client Script help page for more details. 

Try It Out!

A complete working code sample of this widget is attached to this post.

Now, let us see how this Timer widget works:

1. Start the Timer 

Open the widget and select an active case from the dropdown. As soon as you start the timer, a new record will be automatically created in the Timer Entries module to capture the session.

2. Stop the Timer 

When the task is complete, provide a description of the work you have done and stop the timer. The same Timer Entry record (created when the timer was started) will be updated automatically with the end time and your work description.

This forms the foundation for accurate time tracking at the record level. 

In Part 2, we will show how to:

-> Use a workflow and Deluge function to transfer these entries into the Work Log subform inside the relevant Cases record.
-> Use CRM Reports to slice and dice work time for better SLA and productivity insights.

In the meantime, would you like us to address any of your pain-points or have a topic to discuss? Let us know in the comments or reach out to us via support@zohocrm.com.

Until next time, Happy Coding! 

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

Related Reading

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

Idea
Previous Kaizen: Client Script Support for Subforms | Kaizen Collection: Directory


    • Sticky Posts

    • Kaizen #197: Frequently Asked Questions on GraphQL APIs

      🎊 Nearing 200th Kaizen Post – We want to hear from you! 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 #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.
    • Celebrating 200 posts of Kaizen! Share your ideas for the milestone post

      Hello Developers, We launched the Kaizen series in 2019 to share helpful content to support your Zoho CRM development journey. Staying true to its spirit—Kaizen Series: Continuous Improvement for Developer Experience—we've shared everything from FAQs
    • Kaizen #193: Creating different fields in Zoho CRM through API

      🎊 Nearing 200th Kaizen Post – We want to hear from you! 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.
    • Client Script | Update - Introducing Commands in Client Script!

      Have you ever wished you could trigger Client Script from contexts other than just the supported pages and events? Have you ever wanted to leverage the advantage of Client Script at your finger tip? Discover the power of Client Script - Commands! Commands
    • Recent Topics

    • How to insert an Excel/Zoho Sheet table in a chat?

      Hello, is there a way to paste an excel/zoho sheet table to a conversation without loosing table lines. I tried to paste a piece of a table and all the columns and rows were gone. How to easily paste a table without a need of sending a file? Katarzy
    • Mass Update Application Status

      How to update application statuses of Multiple Applications at once? Is that possible? If not then why please consider adding it It can save hours of manual work Thats the only Option I see
    • Free webinar: Streamlining customer service paperwork with the Zoho Sign extension for Zoho Desk

      Hi there! Wondering how to bridge the gap between digitized customer service and business paperwork? Attend our free webinar to learn how you can do this by connecting Zoho Sign, our digital signature app, with Zoho Desk, our online customer service help
    • Mail Search Not Working

      Hello, Mail search is not working at all. I've tried Chrome and Mozilla. I can try and search for an exact term, or even an email that is 1st in my email list. All search does is sit and spin, or it comes up with no results. I've also tried it on my android
    • Cannot Send Email to a Gmail Account

      Hello, I have a zoho-hosted email account, alex@chirochannelnetwork.com that has trouble sending to gmail accounts.  But not all gmail accounts, only some of them. I've tried to figure this out with clients, and they don't appear to be going into their
    • Unblock ME

      info@pentekykloi.gr Unable to send message;Reason:554 5.1.8 Email Outgoing Blocked. Learn more. I purchase additional storage
    • Cannot Print Landscape with Zoho Sheet

      I am noticing that when using the Zoho Sheet desktop for Mac, that even when selecting landscape as the print option, once you choose "Print", a second system dialog opens that automatically makes the view portrait again, and does not allow printing in
    • Power of Automation : Enhancing custom date field calculations by excluding Weekends and Holidays

      Hello Everyone, A Custom function is a user-written set of code to achieve a specific requirement. Set the required conditions needed as when to trigger using the Workflow rules (be it Tasks / Project) and associate the custom function to it. Requirement:
    • Stock count by bin location

      Is there a configuration to make a stock count by bin or area and not by product. these is useful to manage count by area Regards
    • Temporary Outage in Zoho Cliq Affecting US Users – July 23, 2025

      We experienced a service disruption in Zoho Cliq that impacted core functionality for users in the US region. The issue occurred between Jul 23, 2025, 06:54:00 PM IST and 07:13:13 PM IST, lasting approximately 19 minutes. To restore service stability,
    • portal.assignUserInProfile - Não esta adicionando

      Estou encontrando problema com este comando portal.assignUserInProfile Não esta incluindo o usuário no portal Alguém pode me dizer o que pode ser thisapp.portal.assignUserInProfile("teste@gmail.com","Customer");
    • CRM emails vs Campaigns

      Please help me understand this. I am having a difficult understanding of "Campaigns" sent through CRM (real emails) or Zoho One (blast "potentially junk" emails) This is what I currently think emails sent via CRM are "real" emails sent through linked real personal email accounts and therefore are more likely to get delivered.  We use this for critical updates for our "Approved " accounts and certain other preferred statuses emails via Campaigns are sent through the Zoho server (like MailChimp, Campaign
    • Setting up property management in Zoho Books

      Hi, I run a property management business that manages property complexes. There are multiple owners, some owning more than one property on the same complex. My role is to manage the fees they pay for maintenance of common areas, such as the swimming pool
    • Reverse proxy

      We have a web application in the creator platform. When I launch a particular DNS, I would like that DNS to redirect to the web page of the application in creator app. Has anyone achieved it and if yes, please share how to do it.
    • Still client need to download .exe?

      Hello, the client for use zoho assist need everytime download .exe file and launch it?
    • Splitting a ticket's entire thread

      Hi, When you split a ticket it only splits the individual reply that you clicked "Split as new ticket" on. Is it not possible to split the entire ticket thread from that point into the new ticket (every reply from the split point forward)? Or is there
    • Editing the text on the Help Center home page

      Is it possible to edit the "Welcome to Help Center" message anywhere? This one: We'd like to be able to tailor it a little more ourselves.
    • WHMCS for Zoho Flow

      Can we use WHMCS for Zoho flow?
    • Online meetings through Calendar Booking form with options

      This is great to see and particularly for those users who don't have Zoho BOOKINGS. The shame of it all though is that it could have been better. Why do we have to set up separate booking forms for each type of meeting and for each online conferencing
    • Agents permission per department

      Hi Team, can I setup permission for each agent what they can do in each department, for example I want account department agents to only have view access to support department tickets and not allowed to assign or reply to clients. I am sure this would
    • CRM notes

      I want to be able to add notes to a task that do not necessarily get rolled up into an account or contact.   For example, I tasks to work on a Court Order for John Doe divorce account.  There might be lots of updates (in the form of notes) that employees
    • 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
    • Function #8: Add additional charges to invoices

      Here goes one of the highly sought-after custom functions in Zoho Books. If you find yourself needing to apply additional charges to customers on their invoices (say credit card surcharges, or fuel charges applicable to customers from a certain region,
    • Alternative / optional Position

      How do you create an alternative position or an optional position (article) in offers?
    • جمود في الصفحة عند حفظ عمل

      عندما اقوم باضافة ايقونة الى صفحة النموذج تجمد الصفحة ولا تعمل وتصبح مثل المظلة احدث الصفحة لا تعمل انتظر قليلا لا تعمل اقوم بنسخ رابط الصفحة والصقه في الرابط فيعمل
    • ZOHO Books Canadian payroll Integration

      Hello, I know ZOHO books doesn't have Canadian payroll and I dont believe its coming anytime soon. My question is there a Canadian payroll software that could be integrated with Zoho Books? Thank you HD
    • Zoho Desk Time Tracking and the Salary Privacy Issue

      Hello colleagues, Just wondering if anyone did hit the same wall? In the Desk, when the agent-specific hourly rates are enabled (Zoho Desk → Setup → Time Tracking → Billing Preferences), these Time Entries are being displayed in the Ticket History tab.
    • How to Delete, Disable, or Remove Streams from the Mail App?

      Is there a way to remove Streams from the mail app sidebar? I get too many notifications, it doesn't add any value to Zoho's functionality (especially since you can just make comments inside an email), and is distracting. I do not want notifications/alerts
    • Delay in MX updates

      Hi, I set MX Records 12 hours ago, and I am receiving email normally, but I still get notification MX record is not pointing correctly. Error: The MX records of your domain is not yet pointed to Zoho Mail. Why there is a delay in detecting MX records,
    • Bigin iOS and macOS app update: Link email messages to pipeline records.

      Hello everyone! In the latest version of the Bigin iOS(v1.11.9) and macOS(1.8.9) app, we have brought in support for an option to link email to pipeline records. This helps you to view emails specific to a deal, especially when a contact is associated
    • make.com integration

      Just wondering if anyone on Zoho One account connecting apps to Make.com We're on Canadian server (.com) and when connecting to Make.com, it keeps having error of Invalid Client ID. I have contacted both Zoho and Make and both sides said it's not an error
    • Article Numbers for KB articles

      Hello, I was wondering if it's possible to turn on article numbers/ part numbering for KB articles. If this is not already a feature, we'd like to request it. Frequently a solution will require multiple articles so tracking which articles are referenced
    • Refund Request ,Zoho Mail Subscription (zoho suport is not replying)

      Hi Zoho Team, I recently subscribed to the Zoho Mail yearly plan, but after evaluating it, I found that the interface does not suit my workflow. I’ve already canceled the subscription from my end. As I’m well within your 30-day refund window, I’m requesting
    • File Encryption - Zoho Desk iOS app update

      Hello, Everyone! We have now introduced the 'File Encryption' option within the Zoho Desk app as part of the HIPAA Compliance. This option allows the user to encrypt the attachments within the Desk mobile app, which acts as an additional layer of security.
    • Data encryption - Zoho Desk iOS

      Hello, Everyone! In the recent iOS version(v2.8.23) of the Zoho Desk app, we have supported data encryption. As a part of HIPAA Compliance, the Zoho Desk mobile app now allow users to encrypt the Desk mobile database as an additional layer of security.
    • Notify Admin when a user forgets to check-in or check-out at the designated time.

      Hello, I would like notify the Admin via email when a user forgets to check-in or check-out at the designated time. What is the best way to setup this email notification?
    • Assistance Needed with Prospect Conversion Issue

      Hi, I attempted to convert a prospect to an account, but received a pop-up notification indicating that the contact information matches an existing contact. I selected the option to add it to the existing contact, but it appears the prospect was not successfully
    • Mail Merge - unable to send more than 50 email

      Hi, I've subscribed to the pay email service because of the Mail Merge feature. However, I've found that this feature only allow to send up to 50 emails. I've to attach a screenshot for your reference. This limitation is not mentioned anywhere in service.
    • Zoholics Europe 2025: Your Ultimate Data Analysis (Zoho Analytics) Workshop Experience

      Why should you attend? This year, Zoholics Europe 2025 is putting data analysis centre stage. With a dedicated workshop designed to answer all your data-related questions, you’ll gain practical skills, real-time solutions, and expert insights that you
    • UK payroll entries

      Hey guys, Nett payroll payments are imported direct into the bank, using an external payroll system (will be glad for Zoho to have a UK payroll app) At present I have monthly recurring bills for HMRC which are auto entered & paid when due. This seems
    • Next Page