
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
Apps Pane no longer visible
I have read all the info and help and nothing works, I do not have a "show apps" anywhere and I can no longer see my Apps pane in the left hand side of mail, please advise how to get this back
Canvas View - Print
What is the best way to accomplish a print to PDF of the canvas view?
5名限定 課題解決型ワークショップイベント Zoho ワークアウト開催のお知らせ(8/21)
ユーザーの皆さま、こんにちは。Zoho ユーザーコミュニティチームの藤澤です。 8月開催のZoho ワークアウトについてお知らせします。 今回はZoomにてオンライン開催します。 ▷▷参加登録はこちら:https://us02web.zoom.us/meeting/register/eVOEnBsSQ2uvX4WN5Z5DeQ ━━━━━━━━━━━━━━━━━━━━━━━━ Zoho ワークアウトとは? Zoho ユーザー同士で交流しながら、サービスに関する疑問や不明点の解消を目的とした「Zoho
New in Zoho Forms: Inline OTP Verification
Hello form builders, We are excited to announce the launch of Inline OTP Verification in Zoho Forms, a smarter way to ensure the authenticity of the contact details you collect. Until now, OTP Verification in Zoho Forms worked as a pre-access step: respondents
Zoho Mail : Associate emails with Meeting records and allow multiple emails to be assocaited at once
Is there a workaround that would allow either of these? I want to associate emails with Meeting records. I also would like to be able to select multiple emails at once for association with a record.
Create task from email
Is there a way on mobile to create a task from an email? I use this feature a lot and when traveling now I read email on mobile. By the time I get to my office I forget about them since I didn't add it to a task. Is this feature missing on moble?
Zoho Socials - Unable to view Channels and SmartQ
Hi, The channel Facebook has been added by the admin, however, it is not visible on the User level (employee). Other channels are visible. Also, we have the premium account, and SmartQ is not working. Can anyone help? Regards, Priyanka
Eliminating Manual Consolidation: Automating Currency Field Sync from Task to Project
Hello Everyone, A Custom function is a user-written set of code to achieve a specific requirement. Set the required conditions needed as when to trigger using the Workflow rules (be it Tasks / Project) and associate the custom function to it. Requirement:
We want to set the "Converted from Lead" value in Deals using a Workflow or via a Deluge script. How?
For use in Zoho Analytics, we need the field "Converted from Lead" filled in our deal records. This field is empty everywhere, because we do not create deals directly when converting a lead to a contact. We want to do that using the API or a workflow
Sales Orders: Quoted_Items + items in another subform -> into Ordered_Items ?
hello, When creating Sales Orders, is it posible to inherit/fill the Ordered_Items with all the items from Quoted_Items + all the items from a customized subform with similar fields? Since you can create a sales order in different ways (convert, new -
How to cancel the GSTR1 pushed to GSTN
How to cancel the GSTR1 Pushed to GSTN, some rectifications to be done in HSN & SAC code
Zoho Books API — Invalid Operation Type / Scope does not exist
Hello Team, We are unable to use the Zoho Books API from our registered application. We’ve already: Created a client in Zoho API Console using (Admin in Books) Generated the OAuth code and token successfully Used the correct scopes: ZohoBooks.fullaccess,ZohoOauth.userinfo.READ
Enhancements in Canvas
Dear All, Greetings! Canvas lets you design the record details page to suit your brand or business preferences. We are glad to introduce the following enhancements to uplift your design experience. Reusable Components Style Presets Let's go! Reusable
Minimum order quantity
Is there a way to enforce a minimum order quantity - ie has to have a minimum of 250?
【Zoho CRM】ポータル機能のアップデート:UIとポータルの作成フローの変更
ユーザーの皆さま、こんにちは。コミュニティチームの藤澤です。 今回は「Zoho CRM アップデート情報」の中から、ポータル機能のアップデートをご紹介します。 目次 概要 ユーザーグループの作成フローの変更 ユーザーグループ詳細画面内のタブについて 「タブと権限」タブについて 「設定」タブについて 概要 UIとポータルの作成フローが変更されました。ポータルの新機能に先立ち、UIを一部変更しました。タブやオプションの配置を見直し、機能へよりアクセスしやすくなっています。 また、「ポータルユーザーの種類」は今後、「ユーザーグループ」と呼称され、ページ上のボタンも「ユーザーグループを作成する」に変更されます。
Tax on Imported goods charged by Shipping Company
Hi Folks, I imported goods from outside Canada, for better understanding I will give an example data. imported goods value: 2000$ The shipping company sent me an invoice containing the following information: Custom duty on imported goods: 400$ Administration
Prefilled Date fields auto-changed and then locked when using “Edit as new”
If a document out for signature has date fields (not SignedDate fields) that were pre-filled before sending, and then you use “Edit as new” to create a new version of the same document, the value of those date fields gets automatically changed to today
Zoho Webinar via Social Media
Hello, is it possible to stream a Zoho Webinar via Social Media like Linkedin or Facebook?
Add Hebrew & RTL Support to Feedback Widget
Hello Zoho Desk Team, How are you? We are using Zoho Desk and would like to utilize the Feedback Widget. While Zoho Desk itself supports Hebrew and RTL, the Feedback Widget unfortunately does not. We kindly request that Hebrew and full RTL support be
OAUTH2 isn't working with Power Automate and N8N (Zoho Desk)
Hello, I am trying to set up an OAuth2 connection to the Zoho Desk API, but the authentication flow fails immediately. I am experiencing this issue in two separate platforms: Microsoft Power Automate (using a Custom Connector) and n8n. Instead of being
Kit Items Breaking Automations - "Provide mapped components for all kit items"
This has been brought up in other threads, but I believe this issue warrants its own topic. Whenever a sales document (Estimate, Sales Order, Invoice) is created or manipulated programmatically, trying to include a Kit as an Item throws this error: "Provide
Show item Cost value on Item screen
The Item screen shows Accounting Stock and Physical Stock. It would be very helpful if value information could be displayed here as well, for instance Cost Price. Currently, to find the Cost Price (as used for inventory valuations) from inside the item
Mark shipment as delivered via api
Hellloooo again Zoho guys !! More help required if you would be so kind, pleeeezz..... var options = { 'method' : 'post', 'contentType' : 'application/json', 'muteHttpExceptions' : true }; var myPackNo = encodeURIComponent('###################');
Setting Alternative units for an item.
Hello Team, How to create alternate units for an item. We are placing orders for stocks in boxes. One box contain 24 items. At the time of selling we have two categories of buyers wholesalers and retailers. So the sales will be in PCS and in boxes also.
Zoho Inventory search when adding items to SO/PO, etc.
I do not see that Zoho Inventory searches within the item name for an item lookup. We have many products with variants. So when I search for a product, say a lighting system, and it comes in different sizes and colors, I can only get those products where
Item Group Attributes
Hello, I would like to see more attributes under grouped items. We sell car parts, there are several suppliers for the same part but under different brands. We want to group them together but the attributes under groups are lacking. For example, the products
Remove HTML Format - Deluge
Hello @all if you want to delete the HTML format from the text please follow the script. Data = "Text"; info Data..replaceAll("<(.|\n)*?>" , "").replaceAll(" " , " "); Apart from this if you require anything please let me know Thanks & Regards Piyush
Using multiple languages in template
I wanted to add the company name in the template in arabic. I found a way through the header and footer option, except when i print the quotation the arabic disappears both in the top and bottom of the page. I have attached pictures of the before and
ADDING 5% VAT TO PURCHASE ORDERS GENERATED ON ZOHO BOOKS UAE
Please guide on how to add 5% VAT to Purchase Orders generated on ZOHO Books UAE edition.
Import from /csv file, some items fail with the error "Specify Tax Or Tax Exemption".
Hello! I am trying to import a csv file of all of my expenses for a complete financial year. I get errors for some items with the error message "Specifiy Tax or Tax Exemption". These errors only occur on lines where I have "Postage" as the expense account.
About maximum number of requests per minute
Hi, Our company has integrated Zoho inventory and we're using the shipping order creation and update functions and so on. Currently we're receiving "For security reasons you have been blocked for some time as you have exceeded the maximum number of requests
Approval - Report/Views
Hi, On Zoho Desk - Is there a way to report on pending approvals, or a view or similar?
"Zoho CRM Integration" option is missing in Zoho Social Settings
I am trying to integrate my Zoho Social account with my Zoho CRM account. I am on the Professional Trial plan and my user role is "Brand Admin". However, I cannot find the "Zoho CRM Integration" or "Lead Generation" option anywhere in my Zoho Social settings.
Error 553
Não estou conseguindo enviar ou receber e-mail, sempre dando o erro 553, sendo que há mais de um mês o domínio está pago e liberado. Preciso de um suporte urgente
Automate insurance document workflows with Zoho Writer
Insurance companies have to deal with creating and managing complex documents and forms, such as policy applications, explanation of benefits documents, brochures, renewals, and claim forms. Handling all of this manually is hugely time and effort intensive,
Create PDFs with Text so that we can copy from a generated PDF
Currently, any information that a user enters into a field cannot be highlighted and copied from the PDF that Zoho Sign renders. For example, if someone were to provide a phone number in a Zoho Sign text field, you would not be able to copy the phone
How To Insert Data into Zoho Table using Api
Hi Community, I have created a table inside zoho tables. How do I insert data into table using API. Please tell the exact endpoint and payload , I just have to insert data into table columns. Also tell how to find tableid, viewid, baseid etc. which are
How do I delete a folder in Marketing Automation?
Folders are used across contact lists and segments, and email templates. How do I delete a folder once it's been created?
Portal Approval Process
Hi Zoho team and fellow users, I am seeking a method to establish a multi-step approval process between a Zoho user and a portal user (Custom Portal) to review and approve requests through the Custom Portal. For instance, within this setup, one of the
Narrative 8: Intelligent in-app support that's instantly available anytime and anywhere
Behind the scenes of a successful ticketing system - BTS Series Narrative 8: Intelligent in-app support that's instantly available anytime and anywhere The App Support Across Platforms (ASAP) add-on for Zoho Desk is an independent application that integrates
Next Page