Businesses often add contacts to their CRM from various sources, such as email, phone calls, trade shows, and events. While doing so, they may accidentally create multiple entries for the same individual. For example, one contact may appear as "John Smith" created from WhatsApp, another as "J Smith" created through Gmail, and yet another simply as "John," with a business email address. Thankfully, they all share the same phone number.
If you take a cursory look at your CRM, you'll notice a deduplication feature that enables you to identify duplicate contacts based on their email addresses, phone numbers, and account names. Once identified, they get merged together either automatically or manually. However, this deduplication feature does have several limitations: First, it's reactive, fixing duplicates only after they've been created; second, while you can select which field values to keep, it doesn't preserve important information from the duplicate record in addition to the existing data in the master record.
But what if you could proactively clean up duplicate contacts during creation, capture key details from the duplicate, tag the existing record to acknowledge it, and instantly alert your sales team when contacts indicate purchase intent? This is where a custom function—coupled with a workflow rule—offers a more flexible alternative.
Using functions, you can perform a real-time deduplication function that sends alerts, adds tags, and logs key field information as notes in existing records. Then you can connect the function to a workflow rule that triggers every time a contact is created or edited. Read on to learn more.
Permissions and availability
- Users with the Manage Extensibility permission can create connections and write custom functions.
- Users with the Manage Automation permission can create and update workflow rules.
- Users with the Manage Sandbox permission can manage the sandbox.
Requirements
- Create a Zoho OAuth connection with the required scopes for your Zoho CRM account, as detailed in the "Create Connection" section below. Learn more
- Create a workflow rule for the Contacts module that triggers every time a new contact is created or edited in your CRM. Learn more
- Write a custom Deluge function that performs real-time deduplication, sends alerts, adds tags, and logs key field information as notes into existing records. Learn more
- Test the workflow rule in a sandbox before deploying it in your production environment. Learn more
Create a connection
The first step is to create an OAuth connection in your Zoho CRM account.
- Navigate to Setup > Developer Hub > Connections.
- Click Create Connection.
- Select Zoho OAuth under Default Services.
- Specify a Connection Name.
You must enter this name in the code snippet below. - Select the following Scope to request access.
- ZohoCRM.modules.ALL
- Click Create and Connect.
- Click Connect, then click Accept to confirm authorization of access for the scope requested by the client.
Create a workflow rule
The next step is to create a workflow rule linked to a custom function.
- Navigate to Setup > Workflow Rules > +Create Rule.
- Select Contacts from the module dropdown list.
- Provide a name for the rule. For example: "Dedupe contacts proactively".
- Add a description, if required, then click Next.
- In the Execute this workflow rule based on section, do the following:
- Choose Record Action, then select Create or Edit from the dropdown.
- Check the box for Repeat this workflow whenever an Account is edited.
- Click Next.
- In the Which contacts would you like to apply the rule to? section, specify the following conditions:
- <Phone> <is not empty>
- <Email> <is not empty>.
- Click Next.
- Under Instant Actions, select Function and Write your own.
- Provide a Name for the function, as well as a description, if necessary.
- On the Deluge Script Editor, do the following:
- Copy and paste the code given below.
- Click Edit Arguments.
- Choose Contacts - Contact Id, name it contactId, then click Save.
- Click Save & Execute script.
- Click Save on the workflow rule page.
The code
if(email != null && phone != null)
{
searchContact = zoho.crm.searchRecords("Contacts","((Email:equals:" + email + ") or (Phone:equals:" + phone + "))");
info "searchContact : " + searchContact;
}
else if(email == null && phone != null)
{
searchContact = zoho.crm.searchRecords("Contacts","(Phone:equals:" + phone + ")");
info "searchContact : " + searchContact;
}
else if(email != null && phone == null)
{
searchContact = zoho.crm.searchRecords("Contacts","(Email:equals:" + email + ")");
info "searchContact : " + searchContact;
}
if(searchContact.size() > 0)
{
for each contact in searchContact
{
if(contactID != contact.get("id"))
{
rec = zoho.crm.getRecordById("Contacts",contactID);
createdTime = rec.get("Created_Time");
product = ifnull(rec.get("Product"),"");
lastname = ifnull(rec.get("Last_Name"),"");
source = ifnull(rec.get("Lead_Source"),"");
newline = hexToText("0A");
content = "Created Time : " + createdTime + newline + " Contact Source : " + source + newline + " Last Name : " + lastname + newline + "Product Interested : " + product;
notemap = Map();
notemap.put("Parent_Id",contact.get("id"));
notemap.put("Note_Content",content);
notemap.put("se_module","Contacts");
info "notemap : " + notemap;
notecreate = zoho.crm.createRecord("Notes",notemap);
info "notecreate : " + notecreate;
sendmail
[
from :zoho.adminuserid
to :"user@domain.com",contact.get("Owner").get("email")
subject :"Duplicate contact interested again"
message :content
]
tag1 = Map();
tag1.put("name","Contact Interested Again");
tags_list = List();
tags_list.add(tag1);
param = Map();
param.put("tags",tags_list);
recordIDs = List();
recordIDs.add(contact.get("id"));
param.put("ids",recordIDs);
info "param : " + param;
addTag = invokeurl
[
url :"https://www.zohoapis.com/crm/v7/Contacts/actions/add_tags"
type :POST
parameters:param.toString()
connection:"connectionname"
];
info "addTag : " + addTag;
deleteResp = zoho.crm.invokeConnector("crm.delete",{"module":"Contacts","id":contactID});
info "deleteResp : " + deleteResp;
break;
}
}
}
Notes
- Replace "connectionname" with the name of the connection you specified while creating the connection (see the Create a connection section above).
- Make sure to use the accurate API names for their corresponding fields (e.g., "Lead Source") in the code snippet. Learn more
- Customize which fields (e.g. Product Interested) to include in the email notification and notes for the existing contact. For example, you can choose to include or exclude specific field information.
- Customize the subject of the email sent upon creating a duplicate record.
- Customize the tag name (e.g., "Contact Visited Again") that the function will add to the existing contact.
- Replace "user@domain.com" with the email address of the recipient who should receive details about the deleted duplicate record, in addition to the owner of the existing contact record, to indicate renewed customer interest.
- As the API URLs differ for each data center, you should identify your account's data center and use the corresponding domain in the URL. For example, for India, use https://www.zohoapis.in/crm.
Tip
- Configure and test the function in a sandbox to ensure that further development doesn't disrupt your production environment.
Test the solution
- Navigate to the Contacts module.
- Create a contact using the email address and phone number of an existing contact. Additionally, fill in the required fields as specified in the code snippet, including last name, contact source, and product of interest.
- Click Save.
The workflow rule will be triggered. - Check for the following events:
- Refresh the contact page and check whether the duplicate contact has been deleted and moved to the Recycle Bin.
- Check whether an email containing the duplicate contact's metadata was received in the inbox of the specified user, as well as the owner of the existing contact. The subject line of the email should match the one specified in the code.
- Navigate to the existing contact and check if the metadata from the duplicate contact has been added to its Notes section, along with the intended tag.
Did you find this useful? Try it out and let us know how it works. Share this with your team if they'd benefit from it! If you have questions, please don't hesitate to contact us.
More info
- ModuleContacts
- Trigger PointWorkflow Rule
- EditionEnterprise and above
- ComplexityHigh
- Implementation Time60 minutes

Looking for a custom solution?
Contact us, we will help enhance your productivity at lightning speed.
SUBMIT REQUEST