Clay logo, go to homepage
Clay GTM guide

How to Dedupe and Merge Duplicate Accounts in Salesforce

Most duplicate accounts are not hard to merge. They are hard to find. Here is how to surface the duplicates exact-match misses, merge them onto a clean golden record, and stop the next batch from ever forming.

June 1, 20269 min read

Most duplicate accounts are not hard to merge. They are hard to find.

Salesforce will happily hold "Acme Inc", "Acme, Inc." and a record keyed to acme.com as three separate accounts, because to an exact-match rule they are three different strings. The merge itself is the easy, mechanical end of the job. The work is detecting the duplicates that hide behind formatting, deciding which record survives, and keeping new ones from forming the moment you finish. Do it by eye and you miss the ones that matter; run a one-time dedupe and you are back to a messy CRM in a quarter. This is how to find duplicate Salesforce accounts that exact-match misses, merge them onto a clean golden record, and stop the next batch from ever appearing.

What you need before you start:

  • A Clay account connected to Salesforce: With admin or RevOps rights to merge accounts and reparent their child records.
  • A sandbox connected as a Salesforce Test Env: A merge deletes records and cannot be undone, so the first run should not be in production.
  • A rule for which record wins a merge: Decide it before you start, so the survivor is chosen by logic, not by whoever ran the job.

Step 1: Pull the accounts in and normalize the match keys

Duplicates do not collide until the fields you match on look the same.

Import your accounts into a Clay table with the Salesforce integration or a Salesforce SOQL source, and bring in the fields you will match on: account name, website, and any other identifier. Then normalize them, because raw values almost never line up. Run the Normalize Company Name formatter so "Acme Inc", "Acme, Inc." and "ACME INCORPORATED" resolve to one value, and reduce every website to a root domain so www.acme.com/contact and acme.com become the same key. Matching on the normalized fields is what turns three strings that look different into one obvious cluster.

Auto-plays raw account names collapsing into clusters once normalized. Click a cluster to hold it and see what merged into it.

Exact match sees 9 separate accounts

Acme IncAcme, Inc.ACME INCORPORATEDNorthwind LLCNorthwindnorthwind.ioGlobexGlobex Corporationglobex.com
Auto-playing · click to hold

The duplicates were always there; exact match just couldn't see them. Normalizing the name and domain into one canonical key is what makes them collide and become findable.

Step 2: Match and group the duplicates, including the fuzzy ones

Exact match finds the easy duplicates. The expensive ones need judgment.

With normalized keys in place, group the records that refer to the same company. Clay's lookup-and-match methods range from a plain lookup on a shared identifier (a Salesforce account ID or domain) to a lookup plus Clay formulas that pull candidates and apply custom selection logic, to a SOQL lookup with precise acceptance criteria for the hard cases. For the genuinely ambiguous pairs (same company, different entities; a subsidiary versus its parent; a rebrand), add a Use AI column that reads both records and judges whether they are truly the same account, with a reason you can audit.

Use AI column — judge whether two Salesforce accounts are the same company
Judge whether two Salesforce account records are the same company.Record A: name={{Name A}}, domain={{Domain A}}, location={{Location A}}Record B: name={{Name B}}, domain={{Domain B}}, location={{Location B}}Return ONLY JSON:{  "same_company": true | false | "uncertain",  "relationship": "duplicate" | "parent-subsidiary" | "different",  "reason": "<one sentence citing the deciding evidence>"}Rules:- Same registered domain is strong evidence of a duplicate; weigh it heavily.- A subsidiary on its own domain is "parent-subsidiary", not a duplicate.- If the evidence conflicts, return "uncertain" for a human to review. Do not guess.

Step 3: Pick the golden record before you merge anything

A merge is only as good as the record you choose to keep.

Decide the survivor by rule, not by hand. Score each record in a cluster on completeness (the share of fields filled), recency (last activity or last updated), and trustworthiness (rep-verified or enriched-and-verified over a stale import), and the highest score becomes the golden record. Then consolidate the best individual field values onto it, because the surviving record is rarely the most complete on every field: one duplicate may hold the only verified phone, another the current employee count. Build the golden record by taking the best value per field across the cluster, not by blindly keeping one row and deleting the rest.

Auto-builds a golden record by taking the best field from each duplicate. Click a field to see why that value won.

Phone

Employees

Industry

Owner

Last activity

Survivor record0%
Phone
Employees
Industry
Owner
Last activity

The golden record is not simply the most complete row you keep; it is the survivor record ID populated with the best value for each field pulled from across the whole duplicate cluster.

Step 4: Merge in Salesforce without losing history

The merge is where data quietly disappears if you rush it.

Write the consolidated values to the surviving record first with the Update record action keyed on its Salesforce Record ID, so the golden values land on the account that will remain. Then execute the merge in Salesforce, which is the operation that reparents the losing accounts' contacts, opportunities, and activities onto the survivor and retires the duplicates, so no child records are orphaned. Run it against your Salesforce Test Env sandbox first and confirm the right account survived with every related record reattached, because a Salesforce merge deletes the losing records and cannot be undone. Treat the first production merge like a release, not a test.

Auto-plays a merge: write golden values, reparent the children, retire the duplicates. Click a phase to inspect it.

AcmeA2survivor
7 contacts3 opps19 activities
AcmeA1duplicate
7 contacts3 opps19 activities
AcmeA3duplicate
7 contacts3 opps19 activities

Write golden values

0 new records

The consolidated golden values land on the surviving account with the Update action keyed on its Salesforce Record ID — nothing new is created.

Salesforce merge, irreversible · tested in the Salesforce Test Env first

Auto-playing · click to hold

A safe merge writes the golden values to the survivor, then lets Salesforce reparent every child record onto it before retiring the duplicates, so contacts and opportunities are never orphaned.

Step 5: Stop new duplicates from forming

A one-time dedupe is a snapshot. Without prevention, the duplicates grow back.

Cleaning the backlog is half the job; the other half is making sure the next import or form fill matches an existing account instead of creating a fourth Acme. Clay prevents duplicate records by default on write, so an enrichment or sync that finds a match updates the existing account rather than creating one. Set uniqueness fields on your Salesforce imports (a normalized domain is the most reliable key) so re-runs deduplicate themselves, keep Salesforce's own duplicate rules switched on as a backstop, and run the normalize-match-merge workflow on a schedule so any duplicates that slip through are caught while the cluster is still small.

Auto-plays an incoming match updating the existing account instead of duplicating it. Toggle the override to see a duplicate form.

Dedupe at entry

Incoming match — Acme, Inc.

Update existing Acme record

0 duplicates created

No match — Globex

Create a new account

New account, as intended

Override on — Acme, Inc.

Create record despite the match

A fourth Acme is born
1Duplicates prevented
0Duplicates created

Prevention is what makes a dedupe stick: with duplicates prevented by default and a normalized uniqueness key, an incoming match updates the existing account instead of creating the next duplicate.

When the CRM resolves to one clean record per company, every downstream play (routing, scoring, reporting) runs on accounts a rep can trust.

70%

faster campaign launches Legora reached after unifying its prospect and account data in Clay

Read the full story

Common failure modes, and how to avoid them

Most Salesforce dedupe projects fail the same few ways. Watch for these.

  • Matching on raw fields: Exact match never sees "Acme Inc" and "Acme, Inc." as the same account. Normalize name and domain into one canonical key before you match.
  • Keeping the wrong survivor: Picking a survivor by hand keeps stale records and loses good data. Score on completeness, recency, and trust, and build a golden record from the best value per field.
  • Merging before consolidating: A Salesforce merge deletes the losing records, so any unique value on them is gone. Write the golden values to the survivor first, then merge.
  • Merging straight in production: A merge cannot be undone and reparents child records. Run it against the Salesforce Test Env sandbox first and confirm nothing is orphaned.
  • Cleaning once and stopping: Without prevention the duplicates grow back within a quarter. Set uniqueness fields, keep duplicates prevented by default, and re-run the workflow on a schedule.

Outcomes teams report after cleaning and consolidating their CRM with Clay

What teams report after consolidating CRM data on Clay

CompanyOutcomeStory
Anthropic3x data enrichment coverage, several data vendors consolidatedRead
IntercomMultiple data sources consolidated onto one auditable platformRead
OpenAI2x enrichment coverage, scaled single-source to multi-sourceRead

Clay has become the orchestration layer for everything GTM. Salesforce for record-keeping, Snowflake for product data, and Clay for turning it all into automated action.

Dedupe Salesforce and keep it clean

Find the duplicates exact-match misses, merge onto a golden record, and stop new ones from forming.

Frequently asked questions

How do I find duplicate accounts in Salesforce that exact-match rules miss?

Import the accounts into Clay, normalize the fields you match on (run Normalize Company Name and reduce websites to a root domain), then match on the normalized keys. That collapses "Acme Inc", "Acme, Inc." and a record keyed to acme.com into one cluster. For ambiguous cases like a subsidiary versus its parent, a Use AI column can judge whether two records are truly the same company and explain why.

How do I decide which duplicate account to keep when merging?

Choose the survivor by rule, not by hand. Score each record in a cluster on completeness, recency, and trust, and keep the highest as the survivor. Then build a golden record by taking the best value for each field from across the whole cluster, since one duplicate often holds the only verified phone while another holds the current headcount.

Can Clay merge duplicate Salesforce accounts automatically?

Clay does the detection and consolidation: it normalizes and matches records, groups the duplicates, and builds the golden record, then writes the consolidated values to the surviving account with the Update action keyed on its Record ID. The merge that reparents child records and retires the duplicates is executed in Salesforce, which is why you test it in a sandbox first since the merge cannot be undone.

How do I stop duplicate accounts from coming back after a dedupe?

Prevention is what makes a dedupe stick. Clay prevents duplicate records by default on write, so a match updates the existing account instead of creating one. Set uniqueness fields (a normalized domain is the most reliable) on your imports, keep Salesforce's duplicate rules on as a backstop, and re-run the normalize-match-merge workflow on a schedule.

Is merging accounts in Salesforce reversible?

No. A Salesforce merge deletes the losing records and reparents their contacts, opportunities, and activities onto the survivor, and it cannot be undone. Write the consolidated golden values to the survivor first, run the merge against a Salesforce Test Env sandbox to confirm nothing is orphaned, and only then merge in production.