
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
Introducing Import Contract API
We are excited to introduce the Import Contract API in Zoho Contracts. Here's a brief overview: Import Contract API The Import Contract API allows you to import contracts directly into Zoho Contracts in any of the following states: Draft Signed Active
Cambio de Plane
Tenia un plan gratuito, hice una actualización a un plan de pago, salí por completo y entre nuevamente, pero no me deja corregir, pagar o modificar las facturas que había realizado en el modo de prueba. Me da el siguiente error: Factura de proveedor se
Better integration between Zoho CRM and Zoho Bookings
I've noticed that when a meeting which was created in Zoho Bookings is updated by a sales person in Zoho CRM, the change is not reflected back into Zoho Bookings. I have raised this with support who advised that meetings created in Bookings need to be
Why is there a limit to JSONString of less 100 characters
having this problem.
Enhanced crash reporting in Zoho Apptics
All app crashes have the same sad ending: The app dies while the user still wants to use it. But the reason behind each crash? They vary every time. Identifying the root cause and fixing it is already hard work for your dev team. What makes it harder?
Description column in the "all expenses" overview page?
Hi! I'm new to Zoho Books and accounting. I'm surprised there doesn't seem to have a proper "description" field for the expenses, only "notes", and that I can't have such a description visible on the overview page. So that I can quickly visualize my expenses...
Only Default Administrator Profile can Convert Estimates Zoho Finance
In Zoho Finance Only the Default Administrator Profile can convert the Estimates A different Profile with the Admin level permission cannot convert the Estimate of someone else to a Sales Order, Only and only the default Administrator Profile Why is that
Zoho Notebook suddenly running very slow on long notes
I have been a longtime user of Zoho Notebook. Historically, it has run quite well, but I've noticed over the last few days that it has begun to run unbearably slow when typing in large notes, to the point where I can type four words and have to wait for
Is there a way to pass the source of the chat from SalesIQ to the CRM lead creation?
Currently when I update the values of the visitor and the lead is automatically generated in the CRM it says that the lead source is Chat, but in reality it was from either Facebook, Instagram or WhatsApp. Is there a way to make sure that the correct
Imported tasks
Good afternoon, I have recently setup a test instance of Zoho CRM and am currently working through a data migration from Hubspot usine the API migration tool. I needed to get a feel for how seamless this process was but I am running into an issue. It
Assigning Leads to Queues
Do you support Queues as Lead Owner? This is a basic function in any CRM. Assign Lead to a Queue group where any member can take ownership by him self.
Migration of emails from Yandex to Zoho
I am trying to migrate an yandex mail account to zoho mail account. I am confused with all the related articles/informations in the net. Could someone please outline the process to do it, just thinking about me as a novice with limited knowledge or experience. A couple of questions from the knowledge gained. 1. I believe we have to delete the yandex current MX from the website records and add Zoho MX. What happens to the emails as we remove the mail exchange record. Yandex stops updating emails and
Celebrating 200 posts of Kaizen! Share your ideas for the milestone post
Hello Developers, We launched the Kaizen series in 2019 to share helpful content to support your Zoho CRM development journey. Staying true to its spirit—Kaizen Series: Continuous Improvement for Developer Experience—we've shared everything from FAQs
Zoho Sheets working offline
Hi, I am looking for the ability to work offline in Zoho Sheets, but currently I cannot find the process to complete this. Does someone have any ideas or steps I might have missed? Also does Zoho Sheets have the "Format as Tables" function as is currently
Fetching whole month availability via API
We are currently building a custom calendar component that books directly into our client's Zoho Bookings instance. The challenge we are facing is that your API only allows fetching availability one day at a time, which is problematic. Our second workaround
reCAPTCHA
Is the Bookings form protected by reCAPTCHA, or some mechanism to ensure submission of the appointment request form is made by a human vs. bot?
Recent enhancements to Bigin's workflows and Associated Products
Greetings, I hope all of you are doing well! We're happy to announce a few recent enhancements we've made to Bigin. Let's go over each one in detail. Enhancement to workflows Trigger workflows when specific fields are modified to specific values Previously,
Zoho Survey Goes to Junk Folder
Hello, My company is wanting to use Zoho Survey to send out a customer satisfaction survey, and we were wondering if Zoho Campaigns allows the emails to not go into their junk folder. We sent out a test email campaign to our team and for some people it went to their inbox and for others it went to their junk folder. Is there a way to eliminate this from happening? Hope to hear from you soon! Thanks!
Nifty enhancements to Reports in Zoho CRM
Dear Customers, We hope you’re well! We are here with a line of useful enhancements to Reports in Zoho CRM that are readily available to access. Include or exclude Record ID in the report export Display currency fields in record currency Capture report
need a formula to return value as shown (zoho sheet)
Dear folks, What should be the formula in cell B3 to get that output, based on input sheet data.
need a formula to return value as shown (zoho sheet)
Hello folks, what should be the formula in B3, to get the value shown based on input sheet ranges. thanks in advance.
Playground: An exclusive test environment to analyze Field Prediction accuracy
Hello everyone, We are introducing Playground: an exclusive proactive testing environment for businesses to analyze Zia's prediction accuracy. This allows admins and agents to: Run predictions on actual tickets or specific content for realistic test conditions.
Attention: Upcoming changes to Zoho Assist support for older windows versions
At Zoho Assist, our goal is to provide you with secure, reliable, and feature-rich remote support experiences. To maintain this standard, we periodically align our platform with the latest technology and security updates from the broader software ecosystem.
Send again email with link for signup
Hello, I have a lot of problem to send contract my email, also missing the features "share link". How can I send again email to client and me wit link for signup a contract? Everytime it's a disaster!
How do I synchronize a quote to an opportunity?
Hi everyone, We don't quote anything via Zoho but we use it to track services/products so that I can see what was actually sold, vs an opportunity with just shows an amount. We use the quotes for other purposes, mostly to request a quote from Salesforce but we don't invoice or do sales orders or anything. (Basically a user makes a quick quote in Zoho, adds items and pricing, and then exports to PDF which gets emailed to our Quote Desk who then enters the request into Salesforce). Just wondering
Zoho Sprints Android app update: Tags and Epic search
Hello everyone! We are excited to introduce tags and an option to search items within Epic module on the latest Android version(v2.0.2) of the Zoho Sprints mobile app. Let's take a look at these features: Tags You can now create, edit, and delete tags,
Zoho CRM Webhooks - Dynamic URL
Hi Zoho, We've noted a gap in the webhooks function that if improved would increase use cases significantly. The "URL to Notify" field in "Create a Webhook" only supports static information. We have a number of use cases where we could use webhooks more
Work Order Creation Issue
Dear Team, I would like to inquire about the daily limit for Work Order creation in Zoho FSM. Yesterday (02/05/2025) at around 6:30 PM GST, I attempted to create a Work Order, but I have been unable to do so since then. Please find the attached image
Tracking on Zoho Booking
Hi We want to use Zoho Booking for our appointment management. We're using Calendly as of now that lets us track sources of the appointments made including UTM parameters. Is there a way for us to do same with Zoho Bookings?
Pre-created Popular Zoho Flows returns with 404 Error
Your popular Zoho Flows are returning with a 404 page error. This applies to all work flows in your Gallery Space. See video here for further clarification. When will this be fixed? https://drive.google.com/drive/folders/1kDl4ni5EQeLHWeaoIDdtRqoUbW8FNLfO?usp=sharing
CRM Feature Request
When enabling Translation in Zoho CRM I would like to see the ability to remove the language "English (US)". I have encountered a user experience issue with a client recently. The client uses English (UK) but they are based in Spain, so they have activated
Import your Google Docs Spreadsheets into Zoho Sheet
You can now import your Google spreadsheet into Zoho Sheet. This will be useful if you want to switch to Zoho Sheet or if you want to simply try out Zoho Sheet. If you don't have an account with Zoho, you can still try this by signing in with your Google account. Here is a video on how to do this. Note: Existing charts won't appear in spreadsheets you import from Google Docs as the Export functionality of Google Docs doesn't give out the charts. Check out the announcement in our blog: https://blogs.zoho.com/general/import-google-docs-into-zoho-productivity-suite
Support Mixed Visibility Settings in Knowledge Base Categories
Hello Zoho Desk Team, We hope you're all doing well. We’d like to submit a feature request regarding visibility settings in the Knowledge Base module. 🎯 Current Limitation As of today, when a category is set to a specific visibility level (e.g., Public),
Will a campaign send duplicates is same email is on two separate lists
Hi I have two lists to which I want to send campaign. One list is ALL leads and other is list of opportunities and current students. There is overlap between the two lists My question is if I send one campaign to all, will zoho automatically know only to send the email once to the duplicate email?
Time Based Report / Dashboard
We measure our support agent's KPI based on their response time and resolution time from the time the ticket is assigned to them The time based dashboard should provide this information however there is a problem with us referring to this dashboard We
Zoho Learn API Access?
We love using Zoho Learn to manage our internal trainings and knowledge base. What we'd really love is to be able to query Learn via API so that in Zoho Projects, Zoho Creator, or Zoho Desk, we can recommend relevant Learn articles and manuals to team
creating buttons in zoho site
the connection between zoho site and zoho learn will be awesome and amazing feature so the user instead of registering himself twice just one time register on zoho site will be enough and creating accout on zoho learn instead of registering on zoho learn
Two Problems with the Description Field
Our ticket workflow is often like this. Client calls or emails (to a personal email address) reporting a problem. We create a ticket and enter a description. Problems: 1. By my way of thinking when we enter a description, that is an internal comment (unless we mark it public). Yet it seems there is no way to mark it internal, and Desk just starts inserting it into communications. 2. Additionally, in the conversation view it makes it appear it was emailed by the customer and inserts their name on
Lookup Field limitations
Good day all, Is anyone else frustrated with the lookup field limitation? I have an enterprise license, but I only get 10 lookups. Additionally, the custom module has been available for a while and is still in diapers. If you want good reporting, you
Automation#36: Auto-create time-entry after performing the Blueprint transition
Hello Everyone, This week’s edition focuses on configuring a custom function within Zoho Desk to streamline time tracking within the Blueprint. In this case, we create a custom field, and request the agent to enter the spending time within the single
Next Page