Recruiting wants candidate data in CRM “so sales can see who we’re hiring.” Sales wants to know when someone they referred gets hired. HR wants new hires auto-onboarded. Everyone has a reason to sync everything. Do that and you’ll pollute CRM with thousands of candidates who never join, never buy, and never should have been in there.
The right pattern is asymmetric: most candidate data stays in Recruit. Specific events cross over. Here’s the line.
What stays in Recruit
- Candidates in pipeline (applied, screening, interviewing, offer)
- Resume content
- Interview notes
- Offer details
- Rejection reasons
- Source attribution for candidates
This is HR data. It’s protected. It has different retention rules. It does not belong in CRM where 200 sales reps can see it.
What crosses to CRM
- A hire event (creates or updates a Contact for the new employee)
- A referral event (logs touchpoints back to the referring CRM Contact)
- A candidate who is also a customer/prospect (matches by email)
- A rejection of a customer-affiliated candidate (so sales knows not to send a “thanks for applying” email)
Notice the asymmetry: events, not the full record. CRM gets the signal, not the data.
Why the dump-everything approach fails
You sync 8,000 candidates into CRM as Leads. Now:
- Email-marketing accidentally targets candidates with a “Try our product” campaign
- Pipeline reports include leads with
Source = LinkedIn Recruiterthat are not real sales leads - GDPR/data retention rules differ — recruit candidates have shorter retention; CRM doesn’t enforce that
- Duplicates pile up between candidates and existing contacts who applied
The cleanup is harder than the original sync. Don’t do it.
The hire-event integration
When a candidate moves to “Hired” in Recruit, push to CRM. Match by email. Create or update.
// recruit_to_crm_hire
// Trigger: Recruit candidate stage = Hired
candidate = input;
email = candidate.get("Email");
if(email == null || email == "")
{
// can't match without email — log for manual review
zoho.crm.createRecord("Manual_Review", {
"Source": "Recruit",
"Reason": "Hired candidate without email",
"Candidate_Id": candidate.get("id"),
"Created_At": zoho.currenttime
});
return;
}
// Match by email in CRM Contacts
contacts = zoho.crm.searchRecords("Contacts", "(Email:equals:" + email + ")");
if(contacts.size() == 0)
{
// Create new Contact, marked as Employee
new_contact = Map();
new_contact.put("Email", email);
new_contact.put("First_Name", candidate.get("First_Name"));
new_contact.put("Last_Name", candidate.get("Last_Name"));
new_contact.put("Contact_Type", "Employee");
new_contact.put("Employee_Start_Date", candidate.get("Hired_Date"));
new_contact.put("Recruit_Candidate_Id", candidate.get("id"));
zoho.crm.createRecord("Contacts", new_contact);
}
else
{
// Update existing Contact — they were a customer/prospect, now also an employee
contact_id = contacts.get(0).get("id");
zoho.crm.updateRecord("Contacts", contact_id, {
"Contact_Type": "Employee_And_Customer",
"Employee_Start_Date": candidate.get("Hired_Date"),
"Recruit_Candidate_Id": candidate.get("id"),
"Marketing_Opted_Out": true // don't market to your own employee
});
}
The Marketing_Opted_Out on the existing-contact path is critical. The day someone joins the company, marketing should stop emailing them.
The referral event
When a candidate is hired and they were referred by an existing CRM contact, log a touchpoint.
// extend the hire flow
referrer_email = candidate.get("Referred_By_Email");
if(referrer_email != null && referrer_email != "")
{
referrers = zoho.crm.searchRecords("Contacts", "(Email:equals:" + referrer_email + ")");
if(referrers.size() > 0)
{
referrer_id = referrers.get(0).get("id");
zoho.crm.createRecord("Activities", {
"Subject": "Referral hired: " + candidate.get("First_Name") + " " + candidate.get("Last_Name"),
"Type": "Referral_Hired",
"Contact": referrer_id,
"Activity_Date": zoho.currentdate,
"Notes": "Position: " + candidate.get("Position"),
"Referral_Bonus_Eligible": true
});
}
}
Now the AE who owns that contact can send a thank-you. The referral bonus workflow can fire. You haven’t dumped candidate data anywhere it shouldn’t be.
The customer-applied case
A current customer applies for a job. Their email matches an existing CRM Contact. You don’t want to create a duplicate Lead in CRM. You also don’t want sales to find out via the candidate pipeline.
Solution: on candidate create in Recruit, run an email match. If a CRM Contact exists with this email, flag in Recruit as Existing_Customer = true. Recruit team can handle this gracefully. CRM stays clean.
// recruit_candidate_create_check
candidate = input;
email = candidate.get("Email");
if(email != null && email != "")
{
contacts = zoho.crm.searchRecords("Contacts", "(Email:equals:" + email + ")");
if(contacts.size() > 0)
{
zoho.recruit.updateRecord("Candidates", candidate.get("id"), {
"Existing_Customer": true,
"CRM_Contact_Id": contacts.get(0).get("id")
});
// Notify recruiting lead — handle carefully
zoho.cliq.directMessage("[email protected]", {
"text": "Heads up: candidate " + email + " is an existing customer in CRM."
});
}
}
Rejection notification (only when relevant)
If the candidate was flagged as Existing_Customer = true and they get rejected, the recruiting lead needs to know to handle the rejection email personally. Don’t auto-send the standard template. They’re a customer first.
A workflow rule in Recruit: on stage = Rejected, if Existing_Customer = true, route to manual review instead of auto-rejection email.
Data retention discipline
Recruit candidates have legal retention requirements (often 1–2 years post-application, depending on jurisdiction). CRM contacts have different lifecycles. If you sync candidates into CRM, you inherit Recruit’s retention obligations in CRM too. Most legal teams hate that.
Keep the boundary clean. CRM doesn’t get candidate data. Only hire events and matched-existing-customer flags. That gives you the signals without the compliance burden.
What the integration should never do
- Push every applicant into CRM as a Lead
- Sync resume content
- Sync interview scores or feedback
- Send marketing emails to candidates
- Create CRM Contacts for rejected candidates
- Auto-merge candidate records with existing Contacts without explicit confirmation
If your integration does any of these, rip it out. The cleanup is worth the migration pain.
The handoff to onboarding
Hire event in CRM should trigger an onboarding workflow — IT account creation, equipment request, welcome email. That can chain into other systems via webhook. But CRM is the contact-of-record for new hires only because it’s the place where employee + customer + partner identities can live in one shape.
For broader integration patterns and where syncs leak, see Zoho Campaigns CRM sync gotchas. For the underlying scripting habits, see the Zoho Deluge scripting guide.
Bottom line
Recruit holds candidate data. CRM holds customer data. The integration should pass events, not records. Sync hires. Sync referral closure. Flag candidates who match existing customers — in Recruit, not CRM. Never sync full pipelines, resumes, interview notes, or rejection details. The asymmetric pattern is annoying to explain to leadership and cheap to maintain. Bidirectional dumps are easy to explain and expensive forever.