Hey everyone!
Welcome back to another interesting post in the Kaizen series!
Sales teams regularly capture interaction notes in CRM after speaking with prospects. However, drafting a follow-up email that reflects the conversation context can be repetitive and time-consuming.
What if CRM could automatically generate a contextual follow-up email draft based on recent interactions with the lead?
In this Kaizen post, we will create a practical tool that generates context-aware follow-up emails directly from a Lead record. You will see how it pulls recent notes, lead's details, and crafts a ready-to-send draft.
The solution uses three Zoho strengths:
- Widgets for intuitive UI
- Functions for secure backend processing
- External AI APIs (like Groq or OpenAI)
The output displays in the widget. Review, tweak if needed, copy, and paste into your email composer.
The business challenge
Sales reps log calls like "Prospect interested in 20 user licenses but concerned about pricing. Explore volume discounts."
Now, crafting a response involves recalling details, matching tone, and ensuring professionalism. Miss a nuance, and trust erodes.
Our AI generator automates this. It scans the lead's details (name, company, status) and the three most recent notes, then prompts an AI model for a draft.
Example output

Subject: Follow-up on CRM Licensing Discussion
Hi John,
Thanks for the insightful chat today about your team's CRM needs. You're considering licenses for around 20 users, and I appreciate pricing being a top priority.
I'll review our volume options and discount eligibility right away. Expect specifics by EOD tomorrow.
Best regards,
[Your Name]
This keeps the rep in control while slashing draft time from 10 minutes to 10 seconds. Scalable for high-volume teams.
High-level architecture
Think of a layered cake!
- UI Layer (Widget): Button launches it; displays, copies the draft, and sends the email.
- Logic Layer (Function): Fetches CRM data server-side, builds prompt, calls AI securely.
- AI Layer: External service generates natural language.
Flow
Rep clicks a button → Widget gets Lead ID → Calls function → Function queries CRM + AI → Draft back to widget
Secure (no client-side keys), reliable (server-side), and reusable across modules.
Developers often wonder "Why not fetch AI responses straight from widget JavaScript?"
Widgets run in a browser iframe, so embedding API keys exposes them to inspection or misuse. CORS policies can also block external requests, and complex logic like prompt building suits server-side better.
So, the best practice is to use widgets for UI and functions for secure server-side work. This hides credentials and reuses logic.
Follow these steps to build this solution.
Step 1: Add the custom Button
- Head to Setup → Modules and Fields → Leads → Buttons → Create New Button.
- Provide the following details:
- Name: Generate AI Email
- Placement: Record Detail Page (top or bottom)
- Action: Open Widget (select your widget once built)
- Save and add to layout.
- Test: Button appears on Leads; clicking loads widget in context.

Pro tip: Position near the "Send Email" button for seamless workflow.
Step 2: Build the CRM Function
- Go to Setup → Developer Hub → Functions → + Create Function.
- Enter the display name, function name, description, choose Standalone as the category.

- Click Create. The Functions IDE opens.
Enter the following function code. Note that this example uses Groq AI API.
string standalone.generate_ai_email(String leadId) {
lead = zoho.crm.getRecordById("Leads",leadId); name = ifnull(lead.get("Full_Name"),""); company = ifnull(lead.get("Company"),""); status = ifnull(lead.get("Lead_Status"),""); // Fetch recent CRM Notes notesResp = zoho.crm.getRelatedRecords("Notes","Leads",leadId); recentNotes = ""; count = 0; for each note in notesResp { noteContent = ifnull(note.get("Note_Content"),""); if(noteContent != "") { recentNotes = recentNotes + "[" + (count + 1) + "] " + noteContent + ". "; } count = count + 1; if(count == 3) { break; } } // Build AI prompt prompt = "You are a sales assistant helping draft follow-up emails. "; prompt = prompt + "Generate a professional follow-up email based on the customer's previous interactions. "; prompt = prompt + "Lead Name: " + name + ". "; prompt = prompt + "Company: " + company + ". "; prompt = prompt + "Lead Status: " + status + ". "; prompt = prompt + "Recent CRM Interaction Notes: " + recentNotes + ". "; prompt = prompt + "Write a professional follow-up email referencing the discussion."; // Sanitize prompt prompt = prompt.replaceAll("\"","\\\""); prompt = prompt.replaceAll("\n"," "); prompt = prompt.replaceAll("\r"," "); // Build AI request message = Map(); message.put("role","user"); message.put("content",prompt); messages = List(); messages.add(message); requestBody = Map(); requestBody.put("model","llama-3.1-8b-instant"); requestBody.put("messages",messages); requestBody.put("temperature",0.4); requestJSON = requestBody.toString(); // Call Groq API response = invokeurl [ type :POST parameters:requestJSON headers:{"Authorization":"Bearer YOUR_API_KEY","Content-Type":"application/json"} ]; // Extract AI email emailContent = ""; if(response.containsKey("choices")) { emailContent = response.get("choices").get(0).get("message").get("content"); } // Return generated email to widget return emailContent; } |
Note for production
- Connections: In the example, the API key is included directly in the function for simplicity. However, production deployments should use Connections instead of hard-coding credentials as they allow developers to store API credentials securely within Zoho CRM and reuse them across multiple integrations.
- Error Handling: Wrap invokeurl in try-catch.
- Limits: Cap notes at 3 to avoid token overflow and tune temperature (0.4 = consistent).
- Logging: Add info prompt before API call for debugging.
- Test: Execute with sample Lead ID. Expect clean email string back.
- Extend: Add phone/email from Lead, or filter notes by date (e.g., last 7 days via criteria).
Step 3: Develop the Widget
The widget provides the user interface for generating and copying the AI email.
When the widget loads, it retrieves the current Lead ID using the CRM widget JS SDK. When the user clicks Generate Email, the widget calls the CRM function and displays the generated email draft.
The widget also provides Send Email and Copy Email buttons that send the email to the lead record's email ID and copies the email content to the clipboard so the rep can past it into the email composer, respectively.
Sample index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style> <!-- Add your style here--> </style> </head> <body> <div class="widget-card"> <div class="widget-header"> <path d="M20 4H4C2.9 4 2 4.9 2 6v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z" fill="white"/> </svg> <h2>AI Follow-up Email Generator</h2> </div> <div class="widget-body"> <div class="email-box-wrapper"> <textarea id="emailBox" placeholder="Click 'Generate Email' to create a contextual follow-up email..."></textarea> </div> <div class="action-bar"> <button class="btn btn-primary" id="generateBtn" onclick="generateEmail()"> <svg width="13" height="13" viewBox="0 0 24 24" fill="none"><path d="M12 2l2.4 7.4H22l-6.2 4.5 2.4 7.4L12 17l-6.2 4.3 2.4-7.4L2 9.4h7.6z" fill="white"/></svg> Generate Email </button> <button class="btn btn-success" id="sendBtn" onclick="sendEmail()"> <svg width="13" height="13" viewBox="0 0 24 24" fill="none"><path d="M2 21l21-9L2 3v7l15 2-15 2v7z" fill="white"/></svg> Send Email </button> <button class="btn btn-secondary" onclick="copyEmail()"> <svg width="13" height="13" viewBox="0 0 24 24" fill="none"><path d="M16 1H4C2.9 1 2 1.9 2 3v14h2V3h12V1zm3 4H8C6.9 5 6 5.9 6 7v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" fill="#3D4354"/></svg> Copy </button> </div> <div class="status-bar" id="statusBar"></div> </div> </div> <script src="index.js"></script> </body> </html> |
Sample index.js
let leadId; let leadEmail; let generatedEmail = "";
// Widget initialization ZOHO.embeddedApp.on("PageLoad", function(data){
if(data && data.EntityId){
leadId = data.EntityId[0];
// Fetch Lead email ZOHO.CRM.API.getRecord({ Entity: "Leads", RecordID: leadId }) .then(function(response){
if(response && response.data && response.data.length > 0){ leadEmail = response.data[0].Email; }
});
}
});
ZOHO.embeddedApp.init();
// --- Helper functions used by email generation/sending --- // function formatEmailText(raw) { /* formatting logic */ } // function textToHtml(text) { /* convert plain text to HTML */ } // function setStatus(message, type) { /* UI status logic */ }
// Generate AI email using a CRM function function generateEmail(){
var req_data = { arguments: JSON.stringify({ leadId: leadId }) };
ZOHO.CRM.FUNCTIONS.execute('generate_ai_email', req_data)
.then(function(response){
if(response && response.details){
generatedEmail = formatEmailText(response.details.output); document.getElementById('emailBox').value = generatedEmail;
}
}) .catch(function(error){
console.log('Function error:', error);
});
}
// Send email using ZRC async function sendEmail() {
const emailContent = document.getElementById('emailBox').value.trim();
if (!emailContent) return;
try {
// Get allowed "From" addresses const fromRes = await zrc.get('/crm/v8/settings/emails/actions/from_addresses'); const fromAddress = fromRes.data.from_addresses[0];
const htmlContent = textToHtml(emailContent);
// Send mail const response = await zrc.post(`/crm/v8/Leads/${leadId}/actions/send_mail`, {
data: [ { from: { user_name: fromAddress.display_name || fromAddress.user_name, email: fromAddress.email }, to: [ { email: leadEmail } ], subject: 'Follow-up', content: htmlContent, mail_format: 'html' } ]
});
console.log('Mail sent:', response);
} catch (error) {
console.error('Send mail error:', error);
}
}
// Copy generated email // function copyEmail(){ /* copy logic */ } |
The ZIP containing the complete index.js and index.html files used in this example is attached at the end of this post.
User experience walkthrough
- The salesperson clicks Generate AI Email on the record detail page and the widget opens.
- The salesperson clicks the Generate AI email button. The widget retrieves CRM context and generates a contextual follow-up email draft.
- The email appears inside the widget, allowing the salesperson to quickly review the generated message, and use the Send Email button to send it to the lead's email ID.
This workflow ensures that AI assists with drafting the message while still allowing the salesperson to review and control the final communication.
Here is a GIF explaining the use case in action.
Key takeaways
This example demonstrates how Zoho CRM developers can integrate generative AI into CRM workflows using platform-native tools.
Combine CRM Widgets for user interaction and Functions for secure server-side processing to safely integrate external AI services without exposing credentials or compromising security.
The same architecture can be extended to build more advanced AI features, such as:
- Automated meeting summaries
- Deal health insights
- Proposal drafting assistants
- Intelligent follow-up recommendations
We hope you liked this post. Let us know what you think in the comments or reach out to us at
support@zohocrm.com.
Cheers!
===================================================================================
Recent Topics
How Can I Collect Payments for Credit Sales Directly from Zoho POS Billing App?
We are currently testing Zoho POS for a retail business and have encountered an issue with collecting payments on outstanding invoices from customers who purchase on credit. When we process a Credit Sale, Zoho POS correctly creates an Unpaid Invoice.
Zoho POS Mobile Sales Price Conflicts & Pricing Discrepancies
We are seeing recurring Zoho POS Mobile conflicts tied to the Sales Price field, even though drivers are not manually changing item pricing. We have also noticed small price differences between POS transactions and Books, sometimes only a few cents. Devices
GrassHopper VOIP Integration
Does Zoho Plan to integrate with Grasshopper to allow the Telephony hookup in Zoho Desk? If not, Can this be passed along for consideration
Creator -Dynamic addition of Customer Portal User Licenses
Hi, We have a Creator App for B2C about to get released. We are experiencing the Portal User license challenge. Unable to predict the number of users who will download and Subscribe. When a User is about Subscribe and the portal licenses does not exists,
Reminder Settings - Time Tracker
On the time tracker in Reminder Settings I created a reminder according to the Zoho manual. But a manager asked me to change the message that goes in the email. Is it possible to change the message? I didn't find that in the Zoho manual. Another question: I configured to receive the reminder everyone who logged in less than 40 hours. Does Zoho consider less than 40 hours of the current week or the whole month? Another situation, I put it so that I and another specific user would receive the notification,
New in Cadences: WhatsApp follow-ups, upgraded limits, and options for add-ons
Hello everyone, We're rolling out two key updates to help you engage better and scale smarter with Cadences in Zoho CRM. Reach customers on WhatsApp, directly from Cadences Previously, Cadences have enabled you to automate follow-ups through emails, calls,
Specific ListView Canvas on Canvas Home Page Always Loads Most Recent ListView, Not the One Specified
I had mentioned this to ZOHO, but I mainly wanted to see if others in the Community are also facing this problem. I created a Canvas ListView for a Custom Module, and then created a Canvas Home page (technically on a tab item, but I'm not sure if that
This user is not allowed to add in Zoho. Please contact support-as@zohocorp.com for further details
Hello, I am the Super Administrator of the Zoho Mail organization for carrytrail.com. The domain has already been verified, but when I try to create the user. I receive the following error: “This user is not allowed to add in Zoho. Please contact support-as@zohocorp.com
Tip #92 – Organize your support operations with Departments – ‘Insider Insights’
Hello Zoho Assist Community! As a support team grows, so does the complexity. Different customers, different products, technicians spread across regions, and each group needing its own way of working. When everyone operates from a single shared space,
Support Plan: Recuring Issue
Hi Zoho Team, Could you please look into this recurring alert and provide clarification on why this restriction is still in place? This issue has become a bottleneck in our workflow, significantly limiting our automation capabilities. We are unable to
Introducing Zoho Office Desktop
Hi users, We are excited to announce Zoho Office Desktop, a single app to install, update, and open Zoho Writer, Sheet, Show, and PDF Editor on Windows and macOS. It includes: One home for every app: Choose the apps you want, and a guided installation
How Can You Find Broken Internal Links Without Checking Every Page Manually?
Broken internal links are a common technical SEO issue. They can send visitors to missing pages, interrupt navigation, and make website maintenance more difficult. On a large website, checking every link manually is simply not practical. So, how can you
Zoho Writer for Android: Q2 2026 updates
Hi users, We are excited to announce the Q2 2026 updates for Zoho Writer for Android. This includes: Formatting parity with the web app: Choose from multiple ordered and unordered list styles, adjust line spacing, apply your custom paragraph styles, change
Zeptomail in the blacklists
Hello, I noticed some hard bounces while sending emails, and upon checking the details, I see that we have been added to the blacklists of certain spam lists: Bounce category: Policy failure Reason: ip-issues Message: 5.7.1 Service unavailable; client
ZohoBooks - "Account transactions" report doesn't have any "Desciptions"
Hi, I'd like to push for this to be included in ZohoBooks: In a "account transactions" report all the numbers are right, but I'd really like to see the "Description" as part of this report, i.e. the line-item-description as I would see it in the bank statement. Essentially all you see is a list of numbers adding up to the total. It is very difficult to see if things are right without being able to see what exactly each transaction refers to. Going into each transaction one-by-one is not a workable
Zoho Projects | Q3 Updates
Hello everyone, Here's a roundup of everything we released from July to September. We have added some new features as well as improved some of the existing ones. Project Financials Finance Integration Integrate your Project with Zoho Books, Zoho Invoice,
Meet your customers on Arattai, from inside Zoho CRM
Hello everyone, Your customers reach you on the apps they already use. Zoho CRM now supports one more: our very own Arattai! When someone messages your Arattai Business number, the conversation arrives in the Messages module in CRM, right beside your
Running Balance
Please add automatically Running balance in ledger view. Taking lot of time, every time to add manually
MAKING ENTRY TIME MORE USER FRIENDLY AND FASTER O PREVENT TAB TIME
I AM CURIOUS TO KNOW IF WE CAN MAKE IT MORE USER FRIENDLY WHILE MAKING BILLS , I MAJORLY USE OVER DESKTOP SO I AM SUGGESTING TO REMOVE TAB TIME WHILE ENTERING BILL OR MAKING INVOICE DIRECT JUMP TO ONLY REGULAR PARTS OF THE BILL . YOURS RAKESH 782866
Unable to export reports despite enabled report export permissions
Hi Zoho Community, We are unable to export reports in Zoho CRM. When attempting an export, we receive the following error: “Cannot Export Report — You do not have permission to export one or more modules used in this report. Please contact your administrator.”
Add Payment Information (like Bank details)
I am using the Free plan of Zoho Books. I need to add the bank details/ UPI details on the invoice. How can I do that. I have added the details in the Bank Section.
Keep Sensitive Customer Data Private with Field Masking in Zoho CRM
Hello CRM community, Customer records in your CRM are often accessible across multiple teams, but not every team needs visibility into every field. A non-sales team, for instance, has no real need to see a contact's mobile number, and a support agent
Generate a Zoho Sign link
From time to time I get a response "I never received your you e-document for electronic signature" is there a way to generate a Zoho Sign link to share.
Notes - Reaction Buttons
Using the native notes option within CRM is fine, it works and the RTF features are great, however, would it be possible - if there isnt already something in place, where we can add a reactions button, similar to teams/whatsapp to show that its been read
Generate a link for Zoho Sign we can copy and use in a separate email
Please consider adding functionality that would all a user to copy a reminder link so that we can include it in a personalized email instead of sending a Zoho reminder. Or, allow us to customize the reminder email. Use Case: We have clients we need to
Need help with importing expenses
I'm using the template downloaded from the application. When I try to import my expenses, I get the message: Duplicate entry in the Expense Date column. Ensure it contains unique values. None of the rows will import. There are duplicate dates, but they
#12 Bringing In A Second Pair Of Hands
Meera's studio became a two-person business in month five. Adding the second person took ten minutes. Working out why Meera herself was showing up as Staff took considerably longer. The Usual Way To Do This Covered in our published General FAQ, with the
How can I add a Custom Field (or Customer_name) to a picklist?
Our workflow is Shopify-->SO -->Picklist-->Package-->Shipment. We would like to have the Picklist template to include a custom field "Customer_Notes" (we have created this field already). This way we get alerted when a customer has notes on their account.
Header Line in Quote product rows
I believe this is an essential feature that Zoho should provide us, when adding products we want the ability to add titles for our product, in quotes: The Solution/Category Title Product1 Product2..... and then it would show the sub-total of that title
Widget Height were destroyed
All widget heights in the Details Canvas view are broken. Moderation Update: This issue with widget heights in Client Script popups and flyouts has been resolved. Widgets should now display at their expected heights.
How to Fix the Corrupted Outlook 2019 .pst file on Windows safely?
There are multiple reasons to get corrupted PST files (due to a power failure, system crash, or forced shutdown) and several other reasons. If You are using this ScanePST.EXE Microsoft inbuilt recovery tool, it only supports the minor corruption issue
👍 Zoho CRM's Notes now gets Reactions and a new look
Moderation update: Currently available in the following DC's CA, AU, CN, UAE, JP, SA - All Editions EU - Free, Standard and Professional Hello everyone, Notes help users capture important updates, collaborate with teammates, and maintain context for records.
Zoho Extensions 101: Building extensions for Zoho People
Hello developers! Welcome to our new video series on building extensions for Zoho People! If you're new to extension development or looking for guidance on building extensions for Zoho People, you're in the right place. We've curated a series of videos
Add @Mention Notifications in Zoho Cliq for Zoho Project Mentions
Hello Zoho Projects Team, We hope you are doing well. We would like to submit a feature request regarding "Projects Bot" Cliq bot notifications for @mentions inside Zoho Projects comments (Tasks and Issues). Current Behavior: At the moment, when someone
Can't connect to POP and SMTP over VPN
I use Thunderbird to access Zoho Mail via POP and SMTP. I have configured an app-specific password for Thunderbird to use. Everything is properly configured and works correctly — until I enable my VPN. I'm using a paid commercial VPN service (Mullvad).
Outgoing Mail Blocked – Suspicious Login Activity (Need Clarification and Solution)
Hello, I’m currently facing an issue where my Zoho Mail account has been blocked due to “suspicious login activity,” and outgoing emails are restricted. Here are the details shown: Block type: Outgoing mail blocked Reason: Suspicious login activity A
Online Payment Fees
We don't take many online credit card payments so the merchant service provider (PayPal) charges us the 2.9% fee for processing the amount. I would like the ability for the fee to be automatically added to the total amount for "ease of payment". We'd
O SalesIQ aceita números do Whatsapp Business com coextistência?
Tenho uma equipe com vários vendedores e cada um deles tem um celular corporativo usando o Whatsapp Business para se comunicar com os clientes. Estamos no plano Zoho One e esses mesmos vendedores também usam o SalesIQ para atender os leads que vem do
Merge Tickets Directly from Contact Page in Zoho Desk
Dear Zoho Desk Support Team, We are writing to request a new feature that would allow users to easily merge tickets directly from the contact page in Zoho Desk. Currently, the only option to merge tickets is from the Tickets list view page, which can
Losing description after merging tickets
Hello, We merge tickets when they are about the same topic from the same client. It happens sometimes. We recently noticed that after the merger only the description from the master ticket is left in a thread. And the slave-ticket description is erased.
Next Page