Integration · Revenue operations
How to build a CRM to marketing automation sync
A rep updates a job title, the marketing platform overwrites it that night, and the rep updates it again. Below is the model behind a sync that settles, the prompts that build it, and the parts that only bite once it is live.
Built with Tray Headless
- System Salesforce
- Step Delta since watermark
- Step Ownership table
- Step Loop breaker
- System Marketo
The ownership table decides every field, and the loop breaker stops a change echoing between the two systems.
The short answer
What is a CRM to marketing automation sync?
Done well, a CRM to marketing automation sync is four things: field ownership decided per field before anything is built, delta syncing instead of full passes, an explicit reconciliation of the two object models, and loop prevention so an update does not bounce between systems forever. Teams usually come unstuck on ownership. Without a field-level decision about which system wins, the two platforms overwrite each other nightly and both datasets become untrustworthy.
What matters here
- Decide ownership per field, in writing, before building. Without it the two systems overwrite each other and nobody trusts either.
- Sync deltas, not everything. A full pass every night burns API limits and hides the change that mattered.
- The object models do not match. A CRM lead and contact are one person in the marketing platform, and pretending otherwise creates duplicates.
- Break loops with an update-source marker. Otherwise a change bounces between systems and consumes the API limit in a day.
- Never sync opt-out state in both directions with equal authority. Consent is a legal record and it needs one owner.
Who this is for
You run marketing operations or revenue operations. Two platforms hold overlapping data about the same people, the sync was configured by somebody who has left, and both teams distrust the other system.
How it works in practice
Everything that sits between a field changing in one system and settling in both.
- 1
Ownership is decided per field, up front
Sales owns title and phone, marketing owns lead score and campaign history, and both are written down before anything runs.
- 2
Only changed records are synced
A delta against the last successful run, so the volume matches what actually happened instead of the size of the database.
- 3
Lead and contact are reconciled to one person
The CRM splits a person across two objects, the marketing platform does not, and the mapping has to be explicit.
- 4
Each write carries an update-source marker
So the receiving system knows the change came from the sync and does not echo it back.
- 5
Consent flows one way only
Opt-out has a single authoritative owner, because it is a legal record instead of a preference field.
- 6
Conflicts are surfaced, not silently resolved
When both sides changed the same field since the last run, somebody is told rather than the newer timestamp winning by default.
What the sync is made of
Two systems that overlap by design. Four parts, and the first one is a decision rather than code.
Field-level ownership
A written table of which system wins per field. This is the whole design, and skipping it is why most of these syncs are distrusted.
Delta syncing
Changed records since the last watermark, not a full pass. API limits are finite and a full sync hides the meaningful change in noise.
An object model reconciliation
Lead and contact map to one person. Handle the conversion event explicitly or you create a duplicate at the exact moment the deal gets real.
Loop prevention
An update-source marker on every write so a change does not echo between systems until the API limit runs out.
The Tray Headless prompts
Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.
Once per project, run
/tray-workflows:set-workspace
to pick the workspace these build in. Point it at a sandbox first.
- 1
Set up, then write the ownership table first
This is the design. Everything else is plumbing.
Headless skills
build-workflowUse build-workflow. The systems in play are Salesforce and Marketo, or whatever we run in those seats. Before building anything, produce a field ownership table: every field that exists in both systems, which one wins, and whether it syncs one way or both. My starting position: sales owns name, title, phone and account relationship. Marketing owns lead score, campaign membership, email engagement and lifecycle stage. Consent and opt-out are marketing-owned and one-way only. Show me the fields that are in both systems and not on that list. Those are the ones that will cause arguments, and they need deciding now rather than at 2am when the sync loops.
- 2
Sync deltas, with a watermark you can trust
A full nightly pass burns the API limit and hides the real change.
Headless skills
build-workflowtray-patternsUse build-workflow. Sync changed records only, against a watermark stored per direction and per object. Take a small overlap on the watermark, a few minutes, so a record modified during the previous run is not skipped. Deduplicate on the receiving side rather than risking a gap. Batch the writes. Both platforms have API limits and both will throttle you, so handle a 429 with backoff rather than failing the run. Record the watermark only after a successful run. A partial failure that advances the watermark silently drops every record in the gap, and nobody finds out until somebody notices a person missing from a campaign.
- 3
Reconcile the object models explicitly
Where duplicates are created, usually at conversion.
The models do not match. A person is one record in Marketo and may be a Lead or a Contact in Salesforce, and the conversion between them is the dangerous moment. Handle these: Lead to contact conversion. The Marketo person must follow the conversion, keeping its history, not become a second person attached to the new contact. A person who exists in Marketo with no Salesforce record. Decide whether that syncs across at all, and under what condition. The same email on both a lead and a contact. That is a CRM deduplication problem surfacing here, and this sync should report it instead of pick one. Key the mapping on the Marketo id stored in Salesforce and the Salesforce id stored in Marketo, not on email. People change email addresses and that breaks an email-keyed sync silently.
Conversion is the moment a deal becomes real and the moment this sync is most likely to duplicate the person. Test it first, not last.
- 4
Break the loops before they start
Otherwise one change consumes the day API limit by lunchtime.
Headless skills
tray-gotchasUse tray-gotchas, then prevent echo. Stamp every write with an update-source marker. When reading changes, skip anything whose last modification carries this sync as the source. Then add a circuit breaker: if the same record syncs more than a handful of times in an hour, stop syncing it, flag it, and alert. That pattern is always a loop or a fighting pair of rules, and it will exhaust the API limit before anybody notices. Also handle a genuine conflict: both systems changed the same field since the last run. Do not resolve it on timestamp. Apply the ownership table, and if the field is owned by neither side conclusively, hold it and surface it.
- 5
Treat consent as a legal record
The one field where a sync mistake is a regulatory problem.
Opt-out and consent sync one way only, from whichever system your privacy policy names as authoritative. Usually the marketing platform. Never let a CRM update re-subscribe somebody. A rep changing a field should not be able to undo an unsubscribe, and a bidirectional sync makes that possible by accident. Record every consent change with its source, timestamp and the run that carried it. When somebody asks why they received an email after unsubscribing, that record is the answer. Then report weekly: records synced per direction, conflicts surfaced, loop breaker trips, API usage against limit, and any consent change that did not originate in the authoritative system. That last one should always be zero.
- 6
Check it end to end, then hand the ownership table over
Because field ownership is a negotiation between two teams.
Run the per-step schema checks and the whole-workflow audit before this touches production. Run in report-only mode for a week first: compute what would change, write nothing, and read the diff with both teams. Then open the same workflow in Tray Build so marketing and revenue operations can amend the ownership table together in the visual canvas. That table is a negotiation between two teams, and it should not need a third to change it.
What it connects to
Two platforms holding the same people, and the places a conflict needs to surface.
Salesforce
Read and write leads and contacts, respecting the ownership table field by field rather than object by object.
Reads and writes
Marketo
Read and write the person record, campaign membership and lifecycle stage, with consent flowing one way only.
Reads and writes
Slack
Surface conflicts and loop breaker trips to both operations teams, because neither will read a log.
Writes
Snowflake
Land the sync history and every conflict, so ownership disputes are settled with data instead of recollection.
Writes
Same build, other stacks
The design does not change if you run something else in one of these seats. The same prompts build it against Microsoft Dynamics 365, Google BigQuery, Microsoft Teams, HubSpot, Databricks or Google Chat.
Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.
Running it in production
Two teams depend on this and both will blame it first. It needs to be observable.
It lives on the platform, not in a terminal window
Delta syncing in both directions, with backoff against two sets of API limits, executes on the same engine with a watermark that survives a failure.
Every write is attributable to a direction
Which system originated a change, and which run carried it. That is how an ownership dispute gets settled in a minute, not a meeting.
Credentials are held by the platform, never hardcoded
Two platform credentials, each scoped to the objects in the ownership table and nothing wider, held in your workspace.
Both teams own the table
Field ownership opens in Tray Build so marketing and revenue operations amend it together, which is the only way it stays current.
The loop breaker is not optional
A record syncing repeatedly in an hour stops and alerts. Without it a single rule conflict exhausts the API limit before lunchtime.
Questions people ask
Why decide field ownership before building?
Because without it the two systems overwrite each other nightly. A rep corrects a title, the platform reverts it, and within a month neither team believes the other system.
Why not sync everything every night?
Because a full pass burns API limits in both platforms and buries the change that mattered in tens of thousands that did not. Deltas against a watermark match the volume to what actually happened.
Where do duplicates come from?
Usually lead to contact conversion. The CRM splits a person across two objects and the marketing platform does not, so unless conversion is handled explicitly the person becomes two people at the moment the deal gets real.
How do I stop a sync loop?
Stamp every write with an update-source marker and skip changes carrying it. Add a circuit breaker that stops any record syncing repeatedly within an hour, because that is always a loop and it will exhaust the API limit.
Should consent sync both ways?
No. Opt-out is a legal record and needs one authoritative owner. A bidirectional sync makes it possible for a CRM edit to re-subscribe somebody who unsubscribed, by accident.
Further reading
Background on the same subject, for the case rather than the build.
Related guides
Revenue operations
How to build lead routing that assigns in seconds
Match the lead to an account first, evaluate rules in a fixed order, catch what they miss, and time it from arrival. The Headless prompts that build it.
Revenue operations
How to build lead deduplication and merge
Detect on a scored rule set, survive the merge with field-level rules, keep the activity history, and never silently reassign an owner. The prompts that build it.
Last reviewed September 2026.