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 #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
    • Kaizen #152 - Client Script Support for the new Canvas Record Forms

      Hello everyone! Have you ever wanted to trigger actions on click of a canvas button, icon, or text mandatory forms in Create/Edit and Clone Pages? Have you ever wanted to control how elements behave on the new Canvas Record Forms? This can be achieved
    • Kaizen #142: How to Navigate to Another Page in Zoho CRM using Client Script

      Hello everyone! Welcome back to another exciting Kaizen post. In this post, let us see how you can you navigate to different Pages using Client Script. In this Kaizen post, Need to Navigate to different Pages Client Script ZDKs related to navigation A.
    • Kaizen #210 - Answering your Questions | Event Management System using ZDK CLI

      Hello Everyone, Welcome back to yet another post in the Kaizen Series! As you already may know, for the Kaizen #200 milestone, we asked for your feedback and many of you suggested topics for us to discuss. We have been writing on these topics over the

    Nederlandse Hulpbronnen


      • Recent Topics

      • Pause(1);

        I'm using scheduler to invoke an interaction via http post with an external service. The schedule code uses a for-each loop that runs so fast my external application's log files get messed-up (they are named by date-time stamp). What I'm suggesting is
      • Integration Request: Elementor

        Integrating Zoho CRM forms with Elementor, the most popular page builder on Wordpress, would be great. I use it for our site, goenergylink.com, and I have had to use Zapier webhooks to be able to connect it with Elementor. The one issue I have run into
      • Ability to Change Visibility of Published YouTube Videos

        Hi Zoho Social Team, How are you? We would like to request an enhancement in Zoho Social regarding the management of already published youtube videos. Currently, after publishing a youtube video through Zoho Social, there is no option to change its visibility
      • Adding anchor links in Zoho CRM email templates

        I know you can add anchor link in Campaigns, but I dont see the option to that in the CRM email template. Am I missing something?
      • openUrl in blueprints

        My customer wants to open a URL at the end of a blueprint transition. Seems this isn't possible right now but it would be very useful. In this thread, https://help.zoho.com/portal/en/community/topic/openurl-not-working the Zoho agent said that it's logically
      • Ability to Add YouTube Video to Playlist During Publishing

        Hi Zoho Social Team, How are you? While publishing YouTube videos through Zoho Social, we noticed that the platform currently does not allow selecting a playlist at the time of publishing. Instead, we can only add the video to a playlist after it has
      • Introducing Zoho Creator's 2025 Release Projection 2

        Hello Creators! I'm Prakash, from the Creator product management team, and today I'm delighted to unveil our next set of features as part of Release Projection 2 for 2025. With thoughtful analysis and planning, we've curated powerful new capabilities
      • Sharing Form Ownership Among Multiple Users

        I would really like the ability to share form ownership among multiple users. It's frustrating to me that if a co-worker wants to make an edit to a form, I have to transfer ownership to them. It would be great if forms could act like google forms, where multiple people can edit a form and view responses. 
      • Marketer’s Space - Ace Your Spooky-Season Marketing with Pre-designed Templates in Zoho Campaigns

        Hello marketers, Welcome back to another post in Marketer’s Space! We’re in Q4, which means that you have endless opportunities to connect with your audience, starting with Halloween campaigns! In this post, we’ll show you how to design the perfect Halloween
      • Zia expands to China with native features and DeepSeek-powered generative AI features

        Hello everyone, We are glad to support Zia native features and Zia generative AI features for our customers in China. From hereon, all AI-features in Desk will be accessible in China data center with the integration of DeepSeek generative AI model. DeepSeek
      • Email in each module

        We have a contact ,module which then has a link to customer assets which in turn the asset has a multiple link to service visits. When we link assets to customers we choose by name and it brings over the associate email via the lookup. Great feature.
      • Global Search placement in the new UI

        Having a hard time with the global search placement in the UI redesign. Surely I can't be the only one. Previously global search placement was perfect. A bar at the top/center of the page. Exactly where you would expect it to be. Since the new UI has
      • Introducing Skill-Based Ticket Assignment

        The goal of every support team is to provide great support, and to do so as fast as they can. To make this possible, it is important that agents spend their time judiciously, especially when they're dealing with a large number of tickets of varying urgency
      • Kaizen #213 - Workflow APIs - Part 1

        Welcome to another week of Kaizen! If you have ever managed complex business processes, you know that Workflows are the quiet backbone of any well-run business process. They keep things moving; assigning owners, sending alerts, keeping deals on track,
      • Browser and address bar hide

        Hi, How i can do hide the address bar with browser headline when i am working on the sheet, because i am using (freeze panes) which i want visible for full work. For your reference here i am attached the screen shot and marked yellow lines which really
      • Cells Border

        Hi I am using Zoho Sheet on S Tab , is there any option to make all border of any cell at once. I think this is very basic which we are missing. This is available in mobile but not in tab or suggest if i am missing this function. And for Tab can you give
      • Zobot and Sales IQ

        What will happen to the Zoho Sales IQ being integrated to the website after creating the Zobot on the website too
      • Help Center and SEO: Any Benefit to My Domain-Mapped Website Ranking?

        First of, I love the Help Center which I've just decided to integrate into my website to replace its old-fashioned FAQs. So much more to achieve there now! Lots of new benefits to the site visitors and to me in terms of organizing and delivering all the
      • Support french language options

        Greetings, I want to use Zoho with the french language portal, however the supplied translation is not very good (google translate). There are many basic mistakes on the main most important sections (my requests, submit a request). Is there a way for
      • Automation #7 - Auto-update Email Content to a Ticket

        This is a monthly series where we pick some common use cases that have been either discussed or most asked about in our community and explain how they can be achieved using one of the automation capabilities in Zoho Desk. Email is one of the most commonly
      • Introducing the Workflow and Actions APIs for Zoho CRM

        We are absolutely thrilled to announce the release of Workflow APIs and Actions APIs in Zoho CRM’s v8 API suite! This powerful new set of endpoints gives developers unprecedented programmatic control over business automation. For years, Workflow Rules
      • Zoho Form URL displays incorrect name

        Hi, I have a form I created called "Design Request form". It displays this way everywhere I look. However, in the URL, it shows up as "DesignJobRequestFormFINAL011325PROOFV1B" and I'm not sure why. I can't find where to fix this. Does anyone have any
      • Consumers are talking about your business. Are you listening?👂

        A loyal customer might be praising your product in a forum. A frustrated user could be posting a harsh review on a public site. An excited partner may have left a comment on your campaign. A domain expert might be deconstructing your product. A prospect
      • What counts as a Temp for Billing Purposes in Workerly

        I'm considering trying this product but am not sure how the temp count is used for billing purposes. For example, if we keep a large data base of 500 potential workers.....are we billed for that or only if they are assigned to a client at a given point
      • Cold emails not allowed?

        I planned to use Zoho Mail to send businesses some cold emails to offer my freelance writing services, but I noticed that the anti-spam policy is very strict -- no commercial emails whatsoever without prior permission from the recipient? I would be very
      • Form name incorrectly displayed in URL

        Hi, I have a form I created called "Design Request form". It displays this way everywhere I look. However, in the URL, it shows up as "DesignJobRequestFormFINAL011325PROOFV1B" and I'm not sure why. I can't find where to fix this. Does anyone have any
      • I can't receive mail

        Hello, I can't receive e-mail. I no longer receive e-mails to the e-mail I received for ​my site. I also edited the DNS settings, but it doesn't work at all.
      • 1‑to‑1 invite missing post-setup (needs re-invite) vs channel invite auto-joins without business prompt

        1. Zoho Cliq 1‑to‑1 external invite The inviter sent a 1‑to‑1 invite to an invitee who didn’t have a Cliq account. After the invitee completed account setup and created a business/organization, the website redirected them to Cliq, where they opened Cliq
      • 【開催報告】東京 ユーザー交流会 Vol.3 2025/10/17 Zoho サービスの活用促進を外部ツールとの連携で実現!

        ユーザーの皆さま、こんにちは。コミュニティチームの藤澤です。 10月17日(金)に新橋で「東京 ユーザー交流会 Vol.3」を開催しました。ご参加くださったユーザーの皆さま、ありがとうございました! この投稿では、当日のセッションの様子や使用した資料を紹介しています。残念ながら当日お越しいただけなかった方も、ぜひチェックしてみてください😊 ユーザー活用事例セッション:Zoho Flowと決済システムの連携 あみろくの岡島さんに、Zoho サービスの活用事例として、Zoho Flow を活用した外部サービスとの連携事例をご共有いただきました。
      • received email opens in a new tab every time I log in

        as per the title: since about when I first made my email account, every single time Ive logged in to view my inbox, a new tab opens for an email I viewed once as if restoring a closed session. I thought I just didnt understand the "starting up" settings
      • Engage with your customers at scale using WhatsApp Marketing Template messages

        Hi everyone, To make it easier for organizations to communicate with customers, Desk now allows you to send individual, mass, and bulk WhatsApp template messages from both the Ticket and Contact modules. How is this going to benefit your business? WhatsApp
      • Importation Tickets error

        Hi, I'm newbie here 🤓 So, i'm importing data from csv, but when I try advance to mapping fields the importer tool show this message: Previously I try import, other data, and not show errors in this step. Some ideas? Best Regards,
      • Showing description in timesheet and timelogs.

        I am wondering if it’s possible in version 5 of Zoho People to have the description show by default or with a manipulation on the user’s part. Let me show you what I mean. As you can see this is the view for the users. Now if they want to see the full
      • Workaround: openURL in Blueprints - An alternate approach

        There is a roundabout way to open a URL in blueprints after a save event. By using the 'onBeforeMandatoryFormSave' in Client Script, you can open an external URL. Now, the problem is, this is designed to be run BEFORE the blueprint is saved, not after,
      • MTD SA in the UK

        Hello ID 20106048857 The Inland Revenue have confirmed that this tax account is registered as Cash Basis In Settings>Profile I have set ‘Report Basis’ as “Cash" However, I see on Zoho on Settings>Taxes>Income Tax that the ‘Tax Basis’ is marked ‘Accrual'
      • Migrate file from Single File Upload to Multi File Upload

        Dears, I have created a new field Multi File Upload to replace the old Single File Upload field. I'd like to ask you guys what is the best way to migrate the files to the new field?
      • Open "Live Chat" from a hyperlink?

        Hi, I often write paragraphs and text on our company website, and usually say you can get in touch with us via live chat. Can the chat window be triggered to pop open without clicking the chat graphic in the bottom window, and use it in a hyperlink? ie:
      • Zoho Sites search box

        Is there a Search box that can be added to a Zoho site? It would be for searching within the site only.
      • What stops me from packaging and shipping an order when the inventory is negative?

        It seems if the inventory value is negative, that Zoho Inventory should not allow me to create a Package and Ship it.   But, there seems to be nothing to stop me from doing that other than when I go to physically package the item and realize that there is no stock. There also seems to be nothing on the screen that even indicates to me that I should not package and ship.  To me this is the fundamental point of an inventory system.  Am I doing something wrong?   
      • Conditional formatting based on another field

        Hi I have two fields on my form stage 1 complete and stage 1 deadline.  I am trying to setup conditional formatting so that if stage 1 complete is after stage 1 deadline the record is highlighted in red. I need both stage 1 complete and stage 1 deadline
      • Next Page