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 book GST paid in zoho books

      hi, i am a new user to Zoho books and not able to book GST paid in books, kindly suggest how i can book it in books. thanks, siddharth
    • I got unknown charge from Zoho

      Good day, I need help disputing a charge I don't know from, zoho. I have ZohoMail and ZeptoMail. I purchase credits for ZeptoMail, and for ZohoMail I am not subcribed.
    • Function 56: Automatically enable the option for customers to pay via bank account

      Hello everyone and welcome back to our series! One of the key features of Zoho Books is its integration with multiple payment gateways, allowing you to receive online payments for your invoices. This ensures faster payments, automates payment tracking
    • Attach Files to Your Notecards and share them on the go!

      Hey everyone! We’re excited to share a feature many of you have been asking for — you can now attach files directly to your text notecards and share with ease! 🙌 This update was built with your feedback in mind, especially for those who wanted a simple
    • Workdrive on Android - Gallery Photo Backups

      Hello, Is there any way of backing up the photos on my android phone directly to a specific folder on Workdrive? Assuming i have the workdrive app installed on the phone in question. Emma
    • How to add a % Growth column for year-over-year comparison (2024 vs 2025)

      Hello, I am trying to build a monthly revenue comparison between 2024 and 2025 in Zoho CRM Analytics. My current setup is: Module: Deals (Affaires) Filter: Stage = Closed Won Date field: Closing Date Grouping: By Month Metrics: Sum of Amount for 2024,
    • How to searchByCriteria records that are under approval?

      I need to search for both approved and pending approval records Is that possible with this method? Or I need to a different method? var priceReqID = $Page.record_id; log(priceReqID); var records = ZDK.Apps.CRM.Price_List_Item.searchByCriteria("Price_Request:equals:"
    • How to add Simple Analytics to Zoho Pages?

      I have a website with Zoho Pages, how do I add Simple Analytics on it? They seem to have code they need to be embedded https://docs.simpleanalytics.com/script
    • Cant seem to delete an email account

      Hello, I have researching for 4 days how to delete an email account and I am absolutely without a clue. The email account I am trying to delete is support<AT>fyshoes<dot>com. It's the first email account I made and it (is???) was associated with the super user (me). I have since changed it to adming<AT>fychoes<dot>com and I see the support email in my list but I just cant seem to get rid of it. Ultimately I want to associate that email account with another user that I want to add. This is really
    • Import data into Multi-Select lookup field from CSV/Excel

      How to import data into a multi-select lookup field from the CSV/Excel Sheet? Let's say I have an Accounts multi-select lookup field in the Deals module and I want to import the Deals with Accounts field. Steps:- 1. Create/edit a multi-select lookup field
    • Script that deletes a record?

      We're using WP Plugin "Integration for WooCommerce and Zoho Pro", and have created a couple of Feeds to send data to Zoho. We are trying to create Contact records, but only based upon condition. Tried to make it with small Deluge function and Workflow,
    • A formula that capitalises the first letter of each word

      Hi all, is there a zoho formula that can capitalise the first letter of each word in a string? INITCAP only capitalises the first letter of the first word.
    • Quotes in Commerce?

      In Zoho Ecommerce, I need to be able to generate quotes, negotiate with customers, and then generate invoices. Currently, I plan to integrate Zoho CRM to generate quotes. After negotiation and confirmation, I will push the details to Zoho Ecommerce to
    • Zoho Commerce - Mobile Application

      Does Zoho Commerce have a mobile application for customers to place an order?
    • Register user through Phone Number by Generating OTP

      In zoho commerce , I am developing website on online food store Inilialy the user get verification code to their email for registering there account for login. But I need to login using phone number by generating OTP automatically rather than verification
    • Unable to change sales_order status form "not_invoiced" to "invoiced"

      I am automating process of creating of invoice from sales_orders by consolidated sales_orders of each customer and creating a single invoice per customer every month. I am doing this in workflow schedule custom function where i create invoice by getting
    • Custom Buttons for Mass Actions

      Hello everyone, We’ve just made Custom Buttons in Zoho Recruit even more powerful! You can now create Bulk Action Buttons that let you perform actions on multiple records at once, directly from the List View. What’s new? Until now, custom buttons were
    • Zoho Vault Passwords

      Is there a way to consume Zoho Vault Manager passwords using the API? Thanks in advance.
    • Is the ChatGPT Assistant integration capable of recognizing WhatsApp voice messages?

      I was wondering: if a visitor sends me a voice message on WhatsApp, would the assistant be able to transcribe it and reply to them?
    • Zoho Creator to Zoho CRM Images

      Right now, I am trying to setup a Notes form within Zoho Creator. This Notes will note the Note section under Accounts > Selected Account. Right now, I use Zoho Flow to push the notes and it works just fine, with text only. Images do not get sent (there
    • 【Zoho CRM】レポート機能のアップデート

      ユーザーの皆さま、こんにちは。コミュニティチームの藤澤です。 今回は「Zoho CRM アップデート情報」の中から、レポート機能のアップデートをご紹介します。 目次 1. レポートのエクスポート時のレコードIDの表示について 2. 通貨項目の表示について 3. レポートの削除の監査ログへの反映について 1. レポートのエクスポート時のレコードIDの表示について これまで、レポートをエクスポートするとファイルにレコードIDが必ず含まれていました。レコードIDが識別子として役立つ場合もありますが、実際には多くの企業で参照されることはありません。
    • Translation in zoho bookings

      We cant translate zoho booking emails. The general text we can change. But what about text like: ""Here a link to join the meeting online:"" and "Add to Zoho Calendar" and "Add to Google Calendar"? No professional business have mixed languages. Its looking
    • Is there any way to bill one client in different currencies on different invoices?

      I have some customers who have their currency set as USD and most of their billing is done in USD.   However, from time to time I have a need to bill them in my base currency GBP for some specific invoices, but there seems to be no way of doing this that I can see. The only workaround that I can see is to create two client records for the same client, one for USD billing and one for GBP billing, but this is not an ideal situation. Is it likely that the (hopefully!) soon to arrive multi-currency support
    • API name for all fields in Zoho Project (Standard or custom)

      Hi! I struggle to find easily all API name of all field in Zoho Project to build my API rest with other services. We can find them very fast in CRM but not in PRoject.   Could you share a function to get the list of all API Name of any field of an App
    • Disappearing Mouse cursor in Zoho Mail / Windows 11 (Chrome + Edge)

      I'm seeing an issue when writing mails with the light theme with the mouse cursor being white and the document area also being white - making it nearly impossible to see the mouse cursor. I see the problem on Windows 11 under Chrome and Edge. (Yet to
    • Zoho Assist not rendering NinjaTrader chart properly

      Hi everyone. Just installed and testing Zoho Assist. I want to display my laptop' screen (Windows 11) on a monitor connected to my Mac mini. The laptop is running a stock trading program called NinjaTrader. Basically, when running, this program displays
    • Link(s) between Notes

      Hello Everyone, It would be great if links could be created between notes. Let's say we have 5 Notes A, B, C , D, E. I would like to be able to link Note A to Note B but not in other way, so no link appears in Note B linking to Note A. An so on, linking
    • Zoho Books | Product updates | August 2025

      Hello users, We’ve rolled out new features and enhancements in Zoho Books. From the right sidebar where you can manage all your widgets, to integrating Zoho Payments feeds in Zoho Books, explore the updates designed to enhance your bookkeeping experience.
    • Feature Request: Assign Documents to Already Entered Bills, Expenses, Invoices, etc.

      Hi Zoho Team, We are regular users of the Documents module in Zoho Books and appreciate its ability to keep financial records well-organized. However, we’ve noticed a limitation: There is no way to attach a document from the "Documents > Files" section
    • I don't see any WITHDRAWL transaction at all

      Hi I manually imported my bank statement to Zoho books today and I am a complete newbie. I have been reading the knowledgebase but unable to fix this. I only see "Uncategorized 91 DEPOSIT transactions". I don't see any WITHDRAWL transaction at all. Also,
    • Shared inbox unable to see replies

      Hi we are a small company me and someone else, we have a shared inbox for our sale@ and contact@ however we have this issue where by if i reply to an email or the other person reply to the email, it does not show it to them and therefore we end up replying
    • Kaizen #136 - Zoho CRM Widgets using ReactJS

      Hey there! Welcome back to yet another insightful post in our Kaizen series! In this post, let's explore how to use ReactJS for Zoho CRM widgets. We will utilize the sample widget from one of our previous posts - Geocoding Leads' Addresses in ZOHO CRM
    • 404 error at checkout

      Our customers are getting a 404 error at checkout. Anyone else with the same problem?
    • FONT Sizing in Notebook

      Hi Kishore - What is the status of adding font sizing to the application? I have several things that I have pasted directly into Notebook and the fonts are HUGE! I would like the ability to highlight them and reduce the font to a legible size. Nothing
    • Can managers Upload documents to their direct rapports?

      Admin employees have the ability to upload documents to employees' files; however, managers do not have add/manage button - is it possible for managers to upload their direct reports' documents, such as absence documents or 121 documents. Is there something
    • Leave balance display for next year

      Is there a way to not have a rollover or not limit the leave balance depending on the date. For example an employee has 10 days leave balance and wants to apply for January leave in December. They cant because the rollover doesnt show the leave balance
    • Please add an “Auto-Apply Unused Credits” toggle

      Hello — please add a simple org-level option to automatically apply unused credits (credit notes, excess payments, retainers) to new invoices and/or bills. An ON/OFF toggle with choices “invoices”, “bills”, or “both” would save lots of manual work for
    • Zoho Books not working/loading

      Hi! I haven't been able to access/load Zoho Books for the past hours. I get a time out (and it is not due to my internet connection). Could you please check this asap? Thank you!
    • Custom Fields with Data Types for Expense and Payments Received in Zoho Books

      Hi all, We are glad to present to you, the option to create Custom Fields for the Expense and Payments received modules in Zoho Books. This also comes with an icing on top of it - Yes, the custom fields can now be created with different data types. Types like Text, Number, Decimal, Amount, Auto Number and Check Box are supported as of now. Rush to the gear icon at the top right corner, select 'More Settings', choose 'Preferences' in the left pane. Click the Expense/Payment preferences where you can
    • Zoho Cliq - Incident alert (Server outage - IN DC) | August 28

      We've received server down alerts and are currently investigating the issue (IN DC) to find the root cause. Our team is actively working to restore normal operations at the earliest. Status: Under investigation Start time: 09:44:21 AM IST Affected location:
    • Next Page