Zapier CRM Series
Zapier CRM Series · 07 / 07Live-testedRun on real accounts with sample data

Two-CRM Contact Sync

Two Zaps keep the same contacts matching across Zoho CRM and a second system, Zapier Tables standing in for “CRM B”, whichever side someone edits. Copying the data was easy. Stopping each Zap’s write from looking like a fresh edit to the other one took three designs.

TriggerContact updated on either side
Steps5 + 9, across two Zaps
ToolsZoho CRM · Zapier Tables · Formatter · Filter
BuiltSep 18 – 21, 2026
All 7 builds
The Two-CRM Contact Sync Zap in the Zapier editor
The Zap itself. Click to see all of it.

Two systems, one customer, and an echo

Sales works in Zoho CRM; a support team works in another tool. The same customer lives in both, and when her phone number changes in one, the other copy goes stale.

Zapier has no two-way sync, so it takes two one-way Zaps. Built naively they loop: Zap 1’s write is a change in the table, so Zap 2 fires and writes back to Zoho, which fires Zap 1 again. Each pass is a billed task doing nothing.

Compare two timestamps, allow 20 seconds

continue if  Last Synced At does not exist          // never synced: first sync
         or  Last Edited  is after  Last Synced At + 20s  // a person edited it
// otherwise the edit landed within 20s of our own write: it’s the echo, stop

Why a flag wasn’t enough

A “last synced by” flag never clears. After one sync, the next real edit is blocked too, and clearing the flag is itself a write that triggers the other Zap.

Why timestamps work

Time moves on by itself, so nothing needs resetting. Each Zap only reads its own trigger data and writes nothing to the record it’s checking.

VersionHow it decided “echo or edit?”What happened
v1 · FlagSkip if Last Synced By is the partner ZapStopped echoes, but also blocked the next real edit
v2 · Flag + resetOn an echo, reset the flagThe reset was a write: a real loop, 13 runs in about two minutes
v3 · Timestamp windowPass if never synced, or edited 20 s+ after the stampReal edits sync both ways; echoes stop at the filter

Two mirrored Zaps, matched on email

Contacts match on email, not name: two people can share a name, not an inbox.

Z1Zoho → Table5 stepsTrigger on contact update · add 20 s to the sync stamp · filter · find-or-create by email · update the row and stamp it.
Z2Table → Zoho9 stepsTrigger on row change · cut-off · filter · split full name into first and last · find the Account · find-or-create the contact · format the time as ISO 8601 UTC · update and stamp.
Zap 1 steps
Zap 1: Zoho → Table.
Zap 2 steps
Zap 2: Table → Zoho.
Zap 1 filter
Zap 1’s guard.
Zap 2 filter
Zap 2’s mirror-image guard.

Zoho Free can’t add fields, so the standard Description field was relabelled “Last Synced At” and holds the time as ISO text, which the filter can still compare as a date.

A real edit goes through, its echo stops

Time (Sep 21)ZapTriggered byResult
4:38:57 pm1 · Zoho → TablePhone number edited by hand in ZohoPassed; row updated and stamped
4:39:04 pm2 · Table → ZohoZap 1’s own write, 7 seconds earlierFiltered; nothing written back
——No further runsLoop closed
Zap 1 run passes
Zap 1 at 4:38 pm: the real edit passes.
Zap 2 run filtered
Zap 2 at 4:39 pm: the echo is stopped.

Edge case: a contact created first in the table ran the chain three times in about 30 seconds, then stopped on its own. Recorded as a known first-creation quirk instead of adding logic for a one-off that ends itself.

What broke, and how I found out

A loop guard that blocked real edits

Version 1 stopped echoes, but on the first live test a real phone change never reached the table. The record still said “written by the sync” from earlier.

A marker that never expires has to be cleared, and clearing is a write.

Version 1 filter
The v1 filter: right on day one, wrong forever after.

The fix that caused the infinite loop

Version 2 reset the flag on every echo. The reset was a write, so it fired the same Zap again, which read the fresh flag as a real edit and pushed it across. Thirteen runs in about two minutes, until I switched both Zaps off.

In a two-way sync, every write is a trigger.

Burst in Zap history
The burst in Zap History, 12:51–12:52 am.

Not shipping a known flaw

Going back to v1 and writing up its flaw was the safe option. I didn’t want to present a sync that silently drops real edits, so I built the timestamp design. When a later error pulled me back toward Paths, I kept the filter-only version: both cases lead to the same next step, so a branch would only add places to break.

The math step crashed on a blank

Subtracting Unix timestamps failed for never-synced contacts with “missing arguments”. Date steps tolerate blanks and the filter compares dates directly, so the math went away.

Design for the first run, when fields are still empty.

Expression error
The error that removed the math step.

A timestamp stored as “09/21/26 03:44PM”

Writing Zapier’s raw current time into a text field stored a readable string the next comparison couldn’t parse. A format step to ISO 8601 before the write fixed it.

Eight hours in the future

The stamp showed Shanghai clock digits labelled as UTC. With both timezones set to UTC the format step only relabelled. Setting the source timezone to Asia/Shanghai forced a real conversion.

“UTC to UTC” is a label, not a conversion.

8 hours off stamp
The 8-hour-off stamp.
Timezone fix
The fix: source timezone set.

A live echo slipped through on a three-day-old date

The filter compared against Sep 18 because the step was bound to an old cached sample. Retesting the trigger first pulled fresh data.

Open the step’s own data in and out instead of trusting a summary.

Formatter output after retest
After retesting the trigger: today’s stamp, plus 20 s.

Trade-offs I chose

The 20-second window

A real edit within 20 s of a sync is treated as an echo. Rare for people, but not impossible.

Last write wins

If both sides change at nearly the same moment, the later sync overwrites the other.

Email is the match key

Changing an email on one side creates a second contact.

Not a sync product

Zapier itself recommends a dedicated tool for high-volume, real-time two-way sync. This build shows the logic.

TaskFlow and every company and person shown are fictional mock data. Built on Zoho CRM Free, Slack and a Zapier Professional trial; the Zaps are switched off now the trial has ended, and every screenshot comes from the real Zapier, Zoho and Slack accounts.

All work

Hiring, or have a process to automate?

Let’s talk.

Send a few lines about the role, or what keeps slipping through.

Write to me

ralphmatthewmarty@gmail.com

Or message me

WhatsApp +63 919 947 0840

Or connect

LinkedIn

Replies within one business day · UTC+8

Good to know

Based in

Central Luzon, PH (UTC+8)

Looking for

Full-time remote roles; contract too

Works

Remote; hybrid or on-site in the Philippines