Build your first Zoho CRM Deluge exercise around one record and one field. Read the record, check the input, make a deliberate update, and read the saved value again.
This example writes a fixed practice note to a custom text field on a test lead. It is a bounded language exercise. It does not qualify the person, send a message, or loop through your live customer database.
Know when Deluge is needed
Deluge is Zoho's proprietary scripting language. Custom functions can extend CRM behavior and workflows, and CRM Deluge Functions have direct CRM integration tasks.
Before writing a function, describe the intended behavior in ordinary language. If a supported configuration rule already meets the requirement, evaluate that simpler route. Use code when the required logic calls for a deliberate sequence of checks and actions that your configuration does not adequately express.
For this exercise, the contract is specific:
- Input: the identifier of a designated test lead.
- Read: confirm the intended lead can be retrieved.
- Condition: compare the current practice-note value with the target value.
- Write: update that field if it differs.
- Verification: read the same lead again and compare the saved value.
- Repeat: report that the target is already present without writing again.
Choose a test record you can inspect and a field reserved for the exercise. Get approval for the change. Do not point the function at an unfamiliar record merely to see whether the syntax works.
The workflow guide covers configuration-led automation. Keep this exercise focused on understanding the script before attaching it to an automatic invocation.
Understand the data and syntax used in the example
The script uses a map to hold a field name and its intended value. A map is a collection of key-value pairs. Here the key identifies the field and the value is the text you want to save.
The update map must use the field's API name. A display label and an API name are not interchangeable. In this example, Practice_Note is a placeholder for the API name of your approved custom text field. Inspect your metadata and replace it before testing.
Use add a custom field if you need to prepare the practice field. Confirm its type and editability; do not reuse a field whose current business meaning you do not understand.
A list holds a sequence of values. This example uses an empty list inside the options map to make the trigger choice explicit. The updateRecord reference documents the trigger option. Here an empty trigger list requests no listed automation triggers for this update; do not confuse that with proving every possible downstream behavior is absent.
A null check asks whether a value is missing. It should happen before you call methods on that value. An empty string is also worth checking for a text argument, because an argument can exist without containing an identifier.
Keep record identifiers as text at the input boundary, then convert for the integration call. Do not route them through a spreadsheet calculation or another representation that could change their digits.
Read one CRM record by ID
Create a standalone function with a text argument named leadId and a text return value. Use the function signature below when supported by your editor, or configure the equivalent argument and return type in the current function interface.
Map the argument to the intended lead's record identifier for your test invocation. A field label such as Lead Name is not the record identifier. Compare the mapped value with the lead you opened before running the script.
The function rejects an absent input, attempts a numeric conversion, and retrieves the record. The getRecordById reference gives the integration-task syntax. Inspect the returned record identity before reaching the write branch.
The read check should not be “the response was nonempty.” An error can also be a nonempty map. The example requires an id and compares it with the requested identifier.
If the read fails, stop and investigate the input, module, and execution context. Do not change the function to create a new lead as a fallback. That would change the exercise from an update into an unreviewed creation process.
Update a field and inspect the response
Replace the field placeholder with your verified custom field API name. Use this only in the intended test environment and against the approved practice lead.
string standalone.write_practice_note(string leadId)
{
moduleName = "Leads";
fieldApiName = "Practice_Note";
desiredValue = "Reviewed in test";
if(leadId == null)
{
return "STOP: missing lead ID";
}
idText = leadId.trim();
if(idText == "")
{
return "STOP: empty lead ID";
}
try
{
recordId = idText.toLong();
before = zoho.crm.getRecordById(moduleName, recordId);
if(before.get("id") == null)
{
return "STOP: read did not return a lead ID";
}
if(before.get("id").toString() != idText)
{
return "STOP: returned ID differs from input";
}
if(before.get(fieldApiName) == desiredValue)
{
return "UNCHANGED: target already present on " + idText;
}
changes = Map();
changes.put(fieldApiName, desiredValue);
triggerNames = List();
options = Map();
options.put("trigger", triggerNames);
writeResult = zoho.crm.updateRecord(moduleName, recordId, changes, options);
info writeResult;
if(writeResult.get("id") == null)
{
return "STOP: update not confirmed; inspect response";
}
if(writeResult.get("id").toString() != idText)
{
return "STOP: update response ID differs from input";
}
after = zoho.crm.getRecordById(moduleName, recordId);
if(after.get("id") == null)
{
return "CHECK: update responded, but verification read failed";
}
if(after.get("id").toString() != idText)
{
return "CHECK: verification record differs from input";
}
if(after.get(fieldApiName) != desiredValue)
{
return "CHECK: saved value differs from target";
}
return "VERIFIED: practice note saved on " + idText;
}
catch(e)
{
info e;
return "CHECK: execution failed; inspect the record before retrying";
}
}
Before the first execution, predict which branch should run. If the practice note is blank, expect the update and verification branches. If it already equals the target, expect the unchanged branch. Write that prediction alongside the record identifier so you can compare intention and observation afterward.
A useful diagnostic record contains the function name, test input, expected branch, returned message, and observed field value. Add the execution time and version you tested using your own review notes. Do not manufacture sample success output and treat it as a completed run.
The change map contains only the practice field. Keep it that way for the first exercise. Adding ownership, stage, and date changes would make the result harder to diagnose.
The function deliberately checks the update response before the verification read. It does not treat reaching the end of an integration call as proof of success. If there is no expected record identifier, inspect the returned error details.
The exception branch does not claim nothing changed. An exception might occur during conversion, reading, updating, or verification. If the write completed and the final read failed, a blind retry could conceal what happened. Inspect the record and execution output first.
For a workflow-enabled variation, review the documented trigger options and the actual workflow before changing the list. Confirm the event, conditions, and repeat behavior on test data. Trigger handling is a separate design decision from whether the field was saved.
Verify the saved record and repeat-run behavior
Open the lead after execution. Compare the identifier and the practice field with the intended test case. Check another field you expected to remain unchanged and inspect any relevant activity.
The return text is an observation from the script, not a substitute for opening the record. Keep the result and the saved value together in your test notes.
Run a small matrix:
| Case | Expected result to check |
|---|---|
| Missing or empty input | Stops before a record update |
| Nonnumeric input | Exception path; no intended update |
| Unavailable record | Read check stops the exercise |
| Valid lead with a different note | Target value saved and verified |
| Same lead already at target | Unchanged response and no update branch |
| Invalid field configuration | Error or failed verification, requiring investigation |
For the repeat run, use the same identifier without changing the field. The comparison should take the unchanged branch. Then change only the test field to another approved practice value and rerun. You are testing the decision the code makes from current data.
Keep the test field's purpose clear when interpreting the result. This script always writes the fixed text Reviewed in test; it does not calculate a new note from another input field. Changing a phone number or qualification value therefore does not change the target text. If your real requirement depends on those values, define the transformation and its missing-value behavior as a separate exercise.
For that variation, create examples of the source data and the output you expect before changing the function. Include an ordinary value, an absent value, and a value that should be rejected. Ask another administrator to check the examples. Then identify which additional reads and branch conditions the new requirement needs.
Keep the original practice function available for comparison until the variation is verified. If the original still works and the variation fails, compare the new input mapping and calculation before investigating the integration call. This gives you a smaller explanation to test and avoids mixing a language-learning exercise with an unbounded cleanup request.
If an input value changes but the expected update does not appear, inspect the invocation argument first. Was the new value actually passed? Then inspect the read result, branch condition, update response, and verification result in that order. Avoid rewriting the update statement before checking whether execution reached it.
This exercise does not include locking or a transaction around the read and write. If another process changes the same field during the test, investigate that interaction. A production design may need a stronger conflict-handling policy.
When verification disagrees with the target, narrow the investigation. First confirm that fieldApiName points to the intended text field. Then inspect the update response and read the field directly on the record. Check whether another configured process changes the same value. Keep each observation tied to the exact identifier and run rather than combining output from several attempts.
Do not solve a failed verification by returning a success message earlier in the function. That would hide the distinction between a request and a saved result. Preserve the separate response check and readback until you understand the mismatch.
For a bulk adaptation, define what a partially completed run means before writing the loop. Some records may reach the target while another fails validation or cannot be read. Keep a per-record result list and an explicit resume decision so a retry does not obscure which records already changed.
A loop exercise can begin with a small list of approved identifiers and read-only checks. Predict how many iterations should occur, record each retrieved identifier, and compare the list with the intended selection. Add the update only after the selection and single-record behavior have both been reviewed.
To prove scope, compare the designated lead with another test lead you did not pass to the function. The code has no record-list loop, but a wrong argument can still update the wrong individual record. Input review remains essential.
Use the AI Assistant to build and debug
The Zoho CRM AI Assistant can inspect metadata, create and explain a CRM function, configure its supported invocation, and run approved tests. It also handles CRM fields, layouts, workflows, Blueprint, reports, imports, and cleanup on request. It makes changes only after you approve.
Inspect the API name and editability of our practice text field in the test CRM. Propose a one-lead function that reads by ID, writes the approved practice value with an explicit trigger choice, and reads it back. After approval, create the function and configure a test invocation. Show the mapped argument, response, saved value, and repeat-run result. Keep deployment to routine workflows separate until we review the tests.
Ask the assistant to explain each guard and failure branch. You should be able to identify where an empty input stops, where a failed response is handled, and why the second run avoids another write.
Use why a workflow did not run when the field update succeeds but the expected automation does not. Use standardize field values for a separately scoped cleanup instead of expanding the practice function without review.
The assistant works inside Zoho CRM and does not operate third-party products. It can prepare the CRM side of an integration while the external system owner verifies that system's operation.
If you want to update the same field across all existing records, treat it as new bulk work. Define the selection, exclusions, current-value policy, progress tracking, failure handling, and recovery plan first. Prove the single-record operation, then review the broader change before applying it.
A for each loop iterates over an explicit collection. Start by logging identifiers from an approved test collection without writing. Do not interpret adding a loop as permission to process every record in the account.
Handle connections, permissions, and live saves
Zoho's CRM Deluge Functions guide covers connections, logging, and exception handling. It also says that saving a Deluge Function immediately updates live code. Check the invocation and associations before saving changes to an existing function.
Use a separate test function or suitable test environment for this exercise. Keep a copy of the prior source and know which saved version each test ran. A successful test against yesterday's code does not verify today's edit.
Confirm the execution permissions and connection requirements for your actual context in Zoho's help docs. Do not copy a connection name from another account or embed credentials in source code. Check access to both the module and the intended field before diagnosing a failure as a language problem.
Keep logs focused on the identifiers, branch, and response information you need to investigate. Avoid dumping complete customer records when a narrow diagnostic would answer the question. Review test output before sharing it with another person.
The custom function guide covers the broader deployment and invocation design. The invokeurl guide covers HTTP calls when that becomes a separate requirement. Neither is necessary to make this first exercise larger.
Finish by recording the input, field API name, intended value, trigger choice, update response, saved result, and repeated-run observation. Those details let another administrator reproduce the exercise and distinguish a working script from an unverified save.