Deluge (Data Enriched Language for the Universal Grammar Environment) is Zoho's built-in scripting language, and it's what turns Zoho from "a CRM with workflow rules" into "a CRM that does exactly what your process needs." Below are a few real patterns we build often, adjusted here as generic examples — you'll need to swap in your own field API names.
Round-robin lead assignment
Standard workflow rules can assign leads to a single fixed owner or a role, but not rotate evenly across a team. A custom function does:
// Custom function triggered on Lead creation
reps = list("rep1@company.com", "rep2@company.com", "rep3@company.com");
counter = zoho.crm.getRecordCount("Leads");
index = counter % reps.size();
assignedRep = reps.get(index);
resp = zoho.crm.updateRecord("Leads", leadId, {"Owner": assignedRep});
The pattern generalizes: instead of a flat list, you can weight it by territory, by current open-deal count per rep, or by working hours — the logic just changes what populates reps.
Alerting on deal stage changes
A common gap in default CRM setups: nobody gets notified when a high-value deal stalls in the same stage too long. This function, attached to a scheduled workflow, checks for that:
staleDeals = zoho.crm.searchRecords("Deals",
"(Stage:equals:Negotiation)and(Modified_Time:before:" + zoho.currentdate.subDay(5) + ")");
for each deal in staleDeals
{
ownerEmail = deal.get("Owner").get("email");
dealName = deal.get("Deal_Name");
sendmail
[
from: zoho.loginuserid
to: ownerEmail
subject: "Deal stalled: " + dealName
message: dealName + " has been in Negotiation for 5+ days with no update."
];
}
Preventing duplicate records before insert
Zoho CRM has built-in duplicate rules, but they only cover exact-match scenarios. For fuzzier checks — same company, different contact — a custom function on the "before create" trigger gives you control:
existing = zoho.crm.searchRecords("Accounts", "(Account_Name:equals:" + accountName + ")");
if(existing.size() > 0)
{
info "Duplicate account detected: " + accountName;
// return false or route to a review queue instead of creating
}
Cross-app automation: CRM deal won → Books invoice
This is the pattern that makes Zoho One's suite genuinely useful rather than just several apps under one login — a function that fires when a Deal moves to Closed Won, and creates the corresponding invoice in Zoho Books automatically:
if(input.Stage == "Closed Won")
{
invoiceData = Map();
invoiceData.put("customer_id", input.Books_Customer_ID);
invoiceData.put("line_items", input.Line_Items);
response = invokeurl
[
url: "https://books.zoho.com/api/v3/invoices?organization_id=" + orgId
type: POST
parameters: invoiceData.toString()
connection: "zohobooks_connection"
];
}
This is a simplified version — in practice this function needs error handling for missing customer mappings, currency mismatches, and partial-payment scenarios, but the core idea (a deal event triggering a finance-system action) is what removes the manual "sales tells finance to invoice" handoff entirely.
A note on maintainability
Deluge functions are easy to write and easy to let sprawl — we've inherited client orgs with 40+ undocumented custom functions where nobody remembers which ones still matter. Two habits worth adopting from day one: name functions descriptively (not func1, func2), and keep a short internal log of what each automation does and why, outside of Zoho itself. Six months later, that log is the difference between a five-minute fix and an hour of archaeology.
If you've got a specific automation you're trying to build and aren't sure it's possible in Deluge (it usually is), tell us what you're trying to do and we'll tell you how.