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 #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

      • Tip #50- A Closer Look at the Unattended Access Dashboard- 'Insider Insights'

        Having complete visibility and quick access to everything you need certainly makes managing multiple remote devices a lot easier, and that is precisely what the Unattended Access Dashboard in Zoho Assist is designed to offer. Once you go to the Unattended
      • How to update custom multi-user field in Zoho Projects?

        I'm trying to update custom multi-user fields in Zoho Projects via a Deluge function in CRM. The code I have so far is below. It works for updating standard project fields and single-line custom fields, but it does not work to update multi-user fields.
      • Tip of the Week #75– Manage your social media messages from a single shared inbox.

        Are you tired of jumping between apps or browser tabs to reply to your business's Facebook and Instagram DMs? Handling customer messages on social media might seem simple, but switching between multiple platforms can easily lead to lost messages, duplicate
      • Zoho Map integration tasks have changed - you need to "Locate all instances of Zoho Map integration tasks in your Deluge scripts by searching for the v1 marker... before 16 January 2026"

        The Zoho Map deluge integration task has been changed (as at 21 October 2025) to provide a more structured, JSON-like response. This change affects all three Zoho Map integration tasks (Geocode, Reverse Geocode, and Distance Between). More details can
      • Using files from Zoho CRM in Gemini/ChatGPT/Claude

        Hi all, I’ve got subscriptions to Gemini and a few other AI tools which I use for tasks like data enrichment, email composition, etc. In our workflow, we often receive various documents from clients — such as process workflows, BRDs/requirement documents
      • Zoho Analytics & Zoho Creator - Modified Time value

        I'm trying to use the Zoho Creator system field 'modified time' in Zoho Analytics, but it's consistently showing 12 hours 'out' In Zoho Creator In Zoho Analytics Is this a constant difference that I just need to correct with a timezone change - or is
      • Portal For Different Apps

        I found some older threads on this but didn't see anything very recent. I'm new to Zoho One so forgive me if my terminology is off a bit. I was hoping set up a single point of entry into Zoho One. So, many of the apps could be found in one single place
      • Calls undetected

        Zoho Voice records indicate my last call ended at 6:00 PM. All incoming and outgoing calls occurred between 6:00 PM and 7:00 PM.
      • Unable to Select Authenticated Domain as Sender

        We’ve already authenticated our domain, but it’s still not appearing in the sender list when we try to run a campaign. Could you please check what might be causing this issue?
      • Zoho Projects - Show Task List as dropdown field on Task records

        Hi Project's Team, I noticed today that there is no field on a task record related to the task list it belongs to. A dropdown would be helpful for quickly moving tasks between lists while in a task. I know that you can go to "Other Actions" and choose
      • My followed tickets extension is not working under the All departments view

        Hi. I've installed the My followed tickets extension. However, when I try to open the extension under the all departments view, I get the following message: 'Sorry, this extension is not supported in the All Departments view.' How can I solve this p
      • Ticket Time Entry to Timesheet

        The title just about sums it up. I have searched here and not found anything relevant, but If I overlooked, then please set me straight.  We have staff that do nothing but close tickets in desk all day long. These tickets represent their timesheet. Is there a way to have this information sync or for a tech to go into their timesheet themselves and sync it with their tickets of the same timeframe?? We waste a ton of time doing timesheets and the old "Clock in/Clock out" isnt detailed enough for us!!
      • Calls undetected.

        The call is not showing on the call log.
      • Calls undetected

        Zoho is not reading calls made.
      • Missing information data Zoho inventory

        there some missing data in Zoho inventory connection. pick list stock counts bin location we have requested it via mail and the support team doesn’t gove feedback. has anyone achieve to get these info or to ask other ya les
      • Calendar Events Issues

        Not able to view scheduled events on my calendar
      • Extensions 101 webinar series: Build, integrate, and monetize with extensions

        Attention developers! Are you ready to take your extension development skills to the next level? We're excited to bring back the Extensions 101 webinar series with an expanded lineup of Zoho products and an introduction to more platform features. Last
      • Where are recordings stored?

        I have hosted a couple of test meeting, used the "record" button to start and stop the recording but I am unable to find where are those recordings saved?  Can anybody help? Thanks
      • Zoho Desk's integration with Microsoft PowerBI delivers advanced analytics insights

        Hello everyone, Gaining advanced insights through reports and dashboards is one of the critical requirements of every business. In addition to key metrics tracked in Zoho Desk, such as agent performance, SLA adherence, and ticket lifecycle, businesses
      • IMAP error message in Zoho mail

        I cannot send emails today. Everything fine for years until today. Get a message: "You are yet to enable IMAP for your account. Please contact your administrator". Does anyone know how to correct this?
      • IMAP stopped working today

        Hello! I've been a paid customer for more than 10 years, IMAP was always working fine. But today this is the error I've got on my iPhone: I've tried toggling the IMAP for my account (Mail -> Settings -> Mail accounts) off and on again, but that did not
      • Multiple columns in a form

        I am evaluating Zoho Creator. However, I am seeing almost no layout control on a form.  Just a basic 1 or 2 column format that is then imposed on the entire form.  That's not going to work for many, many real world cases. We need multiple columns per line, and we need each line/section to occupy a single column or be able to span the columns.   Someone please tell me that I'm missing something and the capability is actually there.  
      • Global search

        Hi! I think it would be great to have a global search that would give you results from all records of a database, no only for a single field of a single form as we have now. Thanks!
      • Any insights about API/v2? Having problem for a while.

        I don't know why it is throwing a 404 error, my report name is correct. Has someone had this issue and how you fix it?
      • Edit QR code with redirect to form

        Guten morgen, wir haben ein Formular Reklamation_erstellen. Dort soll ein QR Code erstellt werden, der im Lieferschein angezeigt wird. Beim Scannen auf dem soll das jeweilige Formular zum BEARBEITEN geöffnet werden. Leider bekomme ich es nur so hin, dass
      • Getting all the ingredients together for baking an app

        Good day everyone. After reading a lot of the help docs and watching videos, I now started on my app. To prevent hours and hours wasted on going down the wrong track, I would like some clarification on the following. But first some background: I have
      • Help Needed with Configuring ZC Microservice

        I'm attempting to create a simple microservice, but am running into problems with scope and auth. Using Custom API Builder, here's my setup: 1. Method: GET 2. Auth: OAuth2 3. User Scope: All users 4. Response: Standard 5. Function: A function that returns
      • Creator Simplified #10: Predefine Form Field Values and Make Them Read-Only for Users

        Hey Creators, Ready for this week's tip in the Creator Simplified series? Today, we will explore how to have read only fields in a form. Use Case: Assume a scenario where the default value for a Department field needs to be English Literature, but you
      • Zoho Mail : Email Outgoing Blocked

        I suddenly received the following message yesterday. I cannot send any mail. Please resolve as soon as possible, I cannot work without sending email. Dear User, We regret to inform you that your email outgoing has been blocked and you will not be able
      • Creator and Tables

        Good day. I am trying to create my first application. I have imported my data into Tables and am creating my app in Creator. I do not see my tables and cannot see how to write forms data to a table. Even the Workflow just uses the form. In one of the
      • customer Name and address details

        i created one application there is no customer details in that . how to add customer details and
      • Recalculate every row in the subform

        Hello, Can anyone help me with a script, please? I have an issue. Sometimes it happens, that in a multi row subform one of the rows show an incorrect row total value. Not really understand how it can happen, if I have a 20 row subform, 19 rows show correct
      • Creating Repeat Forms that remove redundancies

        I wanted to understand if you can make multi-layer forms that reduce the need for users to input information in again and again. We want a form that our suppliers fill out per ingredient they sell, and the end result should have the Ingredient (Section
      • What is the difference between the free plan and the mail lite plan?

        What is the difference between the free plan and the mail lite plan? How many emails can I send per day?
      • Unblock email

        Hi The outgoing mail from a client of me is blocked. I already made tickets and tickets are send to the EU desk but nobody is responding. The problem is already 4 days! There is absolutely no help from the support. I am really not satisfied at all! Can
      • Domain verification failure

        Hello Zoho Support, I purchased my domain directly through Zoho Mail, but the domain verification keeps failing with the message “TXT verification failed.” I’ve already waited and retried several times, but it still won’t verify. Could you please manually
      • Unable to send message;Reason:554 5.1.8 Email Outgoing Blocked.

        My email account is unable to send emails, and I urgently need to use it. How can I resolve this?If there is anything we have done wrong, please let us know in advance so we can actively cooperate to improve. User ID: 850482493
      • URGENT: Email stopped workin - can't access admin panel

        For some reason email sending stopped working. When I try to send an email it fails with "Unable to send message;Reason:451 4.7.1 Temporary system error" I can receive email just fine I see in my notifications some errors about the MX records, however
      • Can I associate an invoice to a Project after the fact?

        We have generated an invoice but would like to assoicate it to a Zoho Project after the fact.  Is there any way to accomplish that? Thanks, Scott
      • Emails I send as a cc or bcc NEVER GO THROUGH TO THA RECEIVER !!

        every time i send a cc or bcc copy of an email to anyone when I’m using my zohomail.com email - no one ever gets the cc of bcc copy if the email: why???? And i triple check that the email addresses are correct; then i get back an email message (EVERYTIME)
      • Next Page