
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:
| |
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 | |
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.
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
-----------------------------------------------------------------------------------------------------------------
Recent Topics
Updating a contact record's multiple select field
Hi folks, I have a multiple select field (called Mailing Lists) in Zoho CRM which I wish to set to the text "Weekly Email" I have created a step in Zoho Flow using a Create or Update Contact. In the Mailing Lists field, I put the text "Weekly Email" (including the quotes) but the flow returns an error requesting a jsondatatype. I have tried {'Weekly Email'} but I still get the same error. Also tried Weekly Email (without the quotes) How do I format an update of a multiple select field with Zoho
CRM module name capitalisation bug ?
HI, I''m writing a deluge script from Desk to create a task in CRM. All is good when I deal with a lead, but not when a contact is involved. It took me days to figure it out. It might be a bug. Here is a snippet of my script // Ticket Description taskMap.put("What_Id",{"id":ticketContactId});
Can I convert Multiline fields from Plain text to Rich Text?
I have added several custom multiline fields (Plain text) in the Zoho CRM module "Accounts" before the Rich Text (RTF) feature was released in 2024. Now I am looking for a way to convert them to Rich Text format. Is there a way to do this? The problem
Webinar Recording: Maximizing Productivity with Bigin's Mobile Apps
Dear Biginners, Hope you're doing well! As part of our ongoing Masterclass series, we’ve just completed an exciting webinar that explores the capabilities of our mobile apps. Whether it’s managing deals, communicating with customers, or meeting deadlines,
Need Help with Zoho CRM Integration
Hello everyone! 👋 I'm currently in the process of integrating Zoho CRM with an Android gaming website focused on Fire Kirin Game. While everything is progressing smoothly, I'd love to get some expert input to make the integration as efficient and seamless
Validating an order by a superior
Hi, I have a very specific use case for Backstage. Let me know if this is possible or how I could get around this (or if there are no workaround). One of my client uses Backstage to manage internal (on site) events. Participants from different departments
Lets Talk Recruit: Key Takeaways from Our India Community Meetups
Welcome back to Let’s Talk Recruit, the series where we bring you real stories, product insights, and community highlights from the world of recruitment. Our last post covered how you can build approval processes with zero follow-ups using Recruit. In
Emails Migration to Zoho
Hi, I am in the middle of a migration from Salesforce to Zoho one. I am stuck on migratiing emails from Salesforce into Zoho. Does anyone have any suggestions?
How to set an automatic BCC recipient
Hi there, is it possible to set a BCC recipient email address that is automatically showing up in the BCC field when you compile an email for a contact or lead? I want pretty much all emails I sent out of Zoho CRM to have the same BCC email recipient,
zoho commerce
"I need to know where to find the wishlist function in Zoho Commerce."
Request to Recover Deleted Task List – Project ID: RIV-MOD-10722
Hi Zoho Team, I hope this message finds you well. My Zoho task list associated with Project ID: RIV-MOD-10722 appears to have been deleted. When I clicked on the task link from the email notification, I received the following message: "Task has been deleted
Error 400 Booking
Added a custom domain to Booking. Am Getting a SSL Error that has some other domain on the SSL and giving a 400 error. Followed instructions and it stated it verified our domain.. However it is not working. Please Help!
Popup Input Fields on Kanban View
Hi, I have modified the default deals module in zoho crm and using it with kanban view , I've configured my blueprint to ask for necessary input fields on stage updates but it only works on the deal details page. What I want to achieve is to show these
Zoho Developer Hangout (ZDH) – Episode 19 | Catalyst for Zoho Developers
Hey developers! Ready to shift gears from writing long Deluge scripts to building with single-purpose functions and powerful service calls? This session is for Zoho developers who are familiar with typical approaches to working in the Deluge environment
Why is it so difficult to login to zoho store dashboard
I have logged in using zoho id and unable to access dashboard from past 30 mins - why is it so difficult to go dashboard of my own store?
Problem with CRM Connection not Refreshing Token
I've setup a connection with Zoom in the CRM. I'm using this connection to automate some registrations, so my team doesn't have to manually create them in both the CRM and Zoom. Connection works great in my function until the token expires. It does not refresh and I have to manually revoke the connection and connect it again. I've chatted with Zoho about this and after emailing me that it couldn't be done I asked for specifics on why and they responded. "The connection is CRM is not a feature to
Zoho Thrive is getting a revamp: Here’s what’s changing
We’re excited to bring you an upgraded Zoho Thrive experience! This update features a more intuitive interface, improved navigation, and enhancements to help you manage your affiliate and loyalty programs with ease. What’s new? A more flexible start:
Narrow Columns for the Calendar Day View
Hello Zoho folks, First off thank you for Zoho Bookings! I have a feature request: the ability to adjust the columns width for the calendar Day View. User Story: Given that I am a Zoho Bookings admin And I am logged-in And I have > 5 staff members When
Using Bookings as a training management system
I'm looking for a system for my company. We need to be able to give clients a way of booking courses with us from a pre-defined schedule. We'll need for them to be able to book, cancel or amend bookings without manual intervention from our side. The system
Multi Vendor store
Are there any options for setting up an online mall or marketplace that supports multiple vendors, like Etsy and Amazon, where a buyer can search across multiple stores within a mall to find products? Each store owner can administer their own products
Related List Client Script
Noticed that now we support Related List Client Script. But I cannot find any guidance regarding this. May I know how to capture the chosen value?
Importing into Multiselect Picklist
Hi, We just completed a trade show and one of the bits of information we collect is tool style. The application supplied by the show set this up as individual questions. For example, if the customer used Thick Turret and Trumpf style but not Thin Turret,
Limited to one Image Attachment in Service Reports
The ability to attach multiple before and after pictures of work performed is a vital feature for many field service companies. Current attachment limit is 10MB. When adding an image to the appointment notes field, it is producing an image with an average
Zoho Forms Layout Limitations Impacting Conversion
Hi everyone, I’m encountering some challenges with Zoho Forms' design and layout limitations, and I believe this is impacting the conversion rate of our website. Our goal is to capture as much information as possible from leads, but for UI/UX reasons,
How to add two columns in Zoho forms
I would like to have two columns in Zoho forms. How can i enable two columns?
Cancelled appointments still block out timeslot
I haven't had to test this before, but I've just found a problem. I had an appointment in a certain timeslot, and that appointment was cancelled. However, Bookings won't let another appointment be booked in that slot - it makes that time unavailable until
Zoho Bookings <> Oulook
When a user has their Outlook connected to Bookings should it be able to recognise existing meetings and not give those as available options ? If so, how long is the sync time : ie If i were to put a private meeting at 3pm in my Outlook, how long would
where i can see estimated revenue
Don't allow scheduling service on same day
Is there a way when setting up a Service for people to schedule to not allow them to schedule it for the same day, only a future date? We don't want people scheduling their meeting/service without giving us time to prepare for it.
ZOHO BOOKINGS, Add Contact settings
How can I edit the add contact form, to change to not mandatory fields email or phone number? thanks
Zoho Please change your ways
I started using Your new Zoho bookings in earnest 3 days ago. What a mistake. Once again, everything is backwards and upside down. I had to spend 5 hours testing how the thing works in order for me to understand how to acutally use it. When i started using google calendar years ago. it took seconds to figure out how it works. Why is that. bc they put everything in places where it makes sense. Today, I needed to add an appointment as well as a time off. Stupid me i added the time off first,
ZOho Booking and CRM integration.
We are using Zoho Booking wiht Zoho CRM in a custom module. Inside our module we use the option to book a meeting with the customer. This part works great we feed the field to the URL and everything work 100%. Now my issue is that I was not able to find
cannot link my email to Zoho CRM
We are reviewing Zoho as we heard it was an easy solution platform, but we have been trying for many days to get anyone at Zoho to schedule call to talk with us. We unsuccessfully have tried multiple times to link email to Zoho. We put in request for
How do I delete a test email address to which I am supposed to send a test email?
How do I delete an email address added to a test email recipient that is no longer needed due to resignation or other reasons?
Happiness Feedback Report
Hello, I want to see all the feedback, which has been left on ratings in a report for all past tickets. Unfortunately, the pre-built happiness dashboard only lets you go back one month. When I create a report, I cannot add the column 'feedback' and I
Interest on late payments
Is this ever going to be implemented on Zoho Books? It's particularly annoying as its been working so well on Zoho invoice for the last year or so.
Awful audio quality
Hi guys I'm using Zoho Cliq (paid) with my team (remote team : France, Madagascar and Tunisia). Unfortunately, we encounter issues everytime on audio call (and more when we use screenshare) with sound quality, audio lag, etc. We spend loooot of time to
How do I see what participants see when I am app sharing in a meeting?
How do I see what participants see when I am app sharing in a meeting? In my view, I only see myself as active, but not the app (keynote on mac)
Items: Custom lookup field with values from a custom module?
Use case: I have created a new custom module called Makes to hold the names of thousands of different manufacturers. I am trying to create a custom lookup field for Items that uses the custom module. I am not able to select the custom module for the lookup
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,
Next Page