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


    • Recent Topics

    • Canva Integration

      Hello! As many marketing departments are streamlining their teams, many have begun utilizing Canva for all design mockups and approvals prior to its integration into Marketing automation software. While Zoho Social has this integration already accomplished,
    • Clone Entire Zoho Boooks Organization, including all transactions for testing & training

      Can Zoho Books support help with direct cloning of entire Zoho Books & Inventory Organization? including all transactions, just like a copy & paste or disk cloning. Is this possible?
    • Can't change login email address in zoho books.

      Hello, Does anyone have any idea how to change login email in zoho books?
    • Zoho Site Vs. Wordpress website - which is better ?

      Hi I  have a Wordpress website  hosted at hostgator.   I use zoho CRM  for leads , customers, scheduling , etc.  I am considering moving my website to zoho sites.  What are advantages  and disadvantages to using zoho site compared to a wordpress website? On a scale of 1 to 10 ,  how good is zoho sites?    zoho sites with being found by potential customer searching the web for products , services? I sell and service business phone systems into local markets in California. My goal would be to increase
    • Bank Reconciliation Reports Do Not Have the Requisite Information Needed for a Proper Bank Rec Report

      Basic accounting practices for bank reconciliations dictate that bank reconciliation reports have the following components: Date or Period of Reconciliation: The report should clearly state the date for which the reconciliation is being performed, typically
    • How to record chargeback in zoho books?

      Hi all, Does anyone know how to record a chargeback transaction in zoho books? Thanks, Mo
    • workflow fields before assigning the ticket when the client opens the case by email.

      I want to create a workflow that forces the technician to complete the mandatory fields before assigning the ticket when the client opens the case by email.
    • Answer to wrong email address

      Hi Everybody! When we receive a customer request (let's call him Peter) on our info@abc.com mail address, we manually forward the email message to Zoho desk (support@). Of course, sender of that message is info@abc.com and Zoho opens a new ticket with "info" as the contact name and info@abc.com as email address (nobody can blame Zoho for doing that). We then edit the ticket and fill in contact name (Peter), account name (Peter Ltd) and email address (peter@mail.com) of the customer. When we answer
    • Zoho Desk nog sending true Gmail

      Desk isn't sending our outgoing e-mail anymore. We can still receive e-mails but not send. I reconnected the email again and disabled the 2FA (to test). If I choose the Desk generated outgoing email address it works just fine. Please assist.
    • Add Hebrew Language Support for Zia Auto-Tag in Zoho Desk

      Dear Zoho Desk Team, We hope this message finds you well. We are currently utilizing the Zia Auto-Tag feature in Zoho Desk, which has proven to be quite valuable for categorizing and organizing tickets based on their content. However, we’ve encountered
    • Footer: Zoho make a big downgrad with new footer option

      Every post about the new footer function is negative and all say: its a big downgrade. The idea behind this new function was: Make it more simple. Great, now its faster and more simple to add an footer. But nobody from zoho team think about the more bigger
    • Need help with Zoho Billing/Subscriptions API

      Hello, We need help in figuring out which APIs to use in the following scenarios to process customer payments and manage subscriptions. When 14 days trial period is over and subscription status in Zoho changes to "TRIAL_EXPIRED" , customer comes back
    • Multiple Filters? Question answered many times, but never satisfactorily

      Hi. I love Zoho Creator.   However, I would like to know more about creating a view that allows users to easily filter the records, using several filters at once.   I know many people have asked this before, and mostly the answer given is "Use the search function, and search in each column for the required parameter"   However, this is not a satisfactory solution for a number of reasons:   1) You have to know the exact value to search for (sometimes the value might be a two or three word answer)
    • Sendmail with filtered report as attachment - Best practice ?

      Salut, I am scripting sendmail workflows with reports attached. I need those reports to be filtered. For example, a 10 subrows order would have 3 different suppliers, and I want those 3 suppliers to receive a copy of the order with only the subrows related
    • Issues w/ Screen Share & Accessing via Mobile Web Browsers

      1. How do I share my screen while still seeing video of myself & paticipants without rebroadcasting the participant video feeds? All other video conferencing tools provide this feature so not sure if it's a setting I'm missing or a programming oversight. 2. How do I know what screen/application I'm sharing? After selecting the screen/application a notice appears however it is appears on the wrong screen leading to confusion about what participants can actually see.  3. How to I allow participants
    • Time Limited Coupon or Expiring Link in Workflows

      I would like to see a feature where I can include a time limited link in Workflow Campaigns. For example: I could link to a sales page with a discount and set the link to expire after 24h. The link would be generated by Campaigns for each campaign sent
    • Option to duplicate views ( ticket and others)

      Hello, I would like to ask for the option to duplicates views, especially ticket views. Often we need to use the views for very particular information, including filtering out custom data. It would be great to allow duplicate an existing View, so it can
    • Option to copy/duplicate Custom Ticket views

      Hi Team, Hope you're all well. I was wondering if you would consider a feature on Custom Ticket views: The option to copy or duplicate an existing custom ticket view It would help tremendously for views with a lot of criteria that could be reused multiple
    • Democratize data visualization across your organization using Chart View in CRM

      Hello everyone - As part of CRM for Everyone, we've introduced a whole new set of features. This announcement will focus on one of them: Chart View. Why did we add this view? To put insights directly in the hands of the people closest to the action. Here's
    • Will Zoho implement DANE?

      I know that setting up DNSSEC and DANE is quite a risky process. But it will improve email security. With DANE, a server can verify a SSL certificate before connecting to the server. There are some RFC related to DANE which can be found here: DNS-based
    • How do I stop Notifications in Mail?

      How does one turn off notifications for our Mail accounts? Why is an answer to such a basic question impossible to find in this community forum? Also, could you point us to the most current user guide so we don't have to spend time asking such fundamental
    • Turning off self view in Zoho Meeting

      Hi Is it possible to turn off/hide self view in meetings?  Cant see any options for it. Thanks
    • Is it possible to hide self view in Zoho Meetings

      Hi - I want to hide my camera view when conducting meetings in Zoho Meetings.  Most of my meetings are one to one with clients & I prefer to focus on them them on the screen? I've searched and cant find any options for this? Thanks Ro
    • Darshan Hiranandani : Can I hide my self-view in Zoho Meetings, and if so, how?

      Hi everyone, I’m Darshan Hiranandani, looking for a way to hide my self-view during meetings in Zoho Meetings. I find that seeing my own video feed can be distracting, and I’d like to know if there’s an option to hide or disable it. Could anyone provide
    • mx.zoho.com servers blacklisted by UCEPROTECTL3

      Hello, An MXtoolbox check for my domain showed that UCEPROTECTL3 has blacklisted all three of the zoho MX servers. I am unable to sign up for Zeptomail service for our company transactional emails until this issue is resolved. But this is out of my hands.
    • How to integrate Zoho CRM, Zoho Forms and a WIX Web Site

      Attached video demonstrates how to use Zoho Forms included in Zoho One, to design a Contact Us form to be embedded into a WIX web site and integrated into Zoho CRM.
    • Events on Calendar disappeared

      hello, Events (e.g. repeating events) disappeared on my calendar for Wed, Oct 2, which led to missing some meetings on that day. What exactly is wrong? This is not the first time this is happening! Please, fix this calendar issue.
    • FICHIER FEC - ZOHO BOOKS

      J'ai testé le fichier FEC, disponible depuis quelques semaines dans zoho books pour les sociétés françaises. C'est une grande avancée car nous allons enfin pouvoir importer facilement (sans avoir à réaliser de complexes rapports dans zoho analytics) la
    • ERROR CODE :550 - Your message to <xxx@xxxxx.xx> was classified as SPAM.

      Hey Team, I'm using Zoho Mail with my own domain, and from some of the recipients I'm receiving following error message: ERROR CODE :550 - Your message to <xx@xxxx.xx> was classified as SPAM. Please add more content, cut down on HTML links, use fewer
    • Allow 3 Subforms in a custom module

      We have many custom modules in CRM and every now and then we need more than 2 subforms for a module We are on Zoho One Plan Can you please increase the subfrom limit from 2 to 3 Our current workaround is to create a solution in Zoho Creator and embed
    • Time Zones

      Hello, Is there a way to add a time zone in a Deal related to "bid due"? We work on projects across the world and even though some things adjust to my own time zone, I have found that any dates we manually enter - Bid Date, RFI Due Date, etc. do not appear
    • Create Zoho Project and assign a contact without account

      I’m trying to automate the creation of new projects in Zoho Projects using Zoho Flow. In my setup, I often need to assign projects to individual contacts who don’t have an associated Account/Company in Zoho CRM—just a personal contact. When I create a
    • Update main form's Lookup value following the completion of a Subform within that same main form

      Hi, It's quite a simple request but I'm struggling with getting the deluge to work smoothly. In short, I have a main form (Place_New_Order). Public users will be able to use it. They have a subform to complete with their contact details etc (name, email,
    • ZOHO LOGIN PROBLEM

      Hello, my name is Bernice. One of the users in our company is having a problem logging into their system. They had two-factor authentication on their phone but unfortunately, they lost that phone. Now when trying to login to their Zoho people they are
    • New in CRM: Dynamic filters for lookup fields

      Last modified on Oct 28, 2024: This feature was initially available only through Early Access upon request. It is now available to all users across all data centers, except for the IN DC. Users in the IN DC can temporarily request access using this form
    • Sync Zoho CRM Events with Google Calendar?

      Hi, Is there a way to permanently sync all events from Zoho CRM with Google Calendar? I’ve seen that you can link Zoho CRM to Zoho Calendar and then connect Zoho Calendar to Google Calendar — but is there a way to sync existing and future events from
    • Pre-fill webforms in Recruit

      I don't want to use the career site portal (as I have my own already), but I would like to direct users to the application forms for each role, from my website job pages. Is there a way to pre-fill fields in Recruit application forms, so that I only have
    • image cover div or original aspect

      I changed my app's theme, and now when I return to the original theme, the images in my reports cover the entire div, whereas before they were displayed in their original aspect ratio. How can I change this? I can't find the option. I only see that you
    • Delete subform rows based on mainform input

      I took my first adventure in getting ChatGPT to write some code for me this weekend. I want to ADD new rows, UPDATE existing rows and DELETE existing rows based on the input of a mulitselect lookup in the mainform. ChatGPT produced this for me which seems
    • Des parcours WhatsApp simples pour engager vos prospects et les convertir durablement

      En tant que professionnel du marketing, il vous est sûrement arrivé de déployer des campagnes par e-mail, SMS, réseaux sociaux ou pop-ups, sans obtenir l'engagement espéré. Une situation frustrante, mais malheureusement fréquente. Vous vous posez sans
    • Next Page