$ dedup scan --by email,phone,name

Merge duplicate FluentCRM contacts
without the one-way delete.

FluentCRM has no merge feature, so the usual fix is a bulk delete you cannot take back. This finds duplicates by normalized email, phone, and name and merges them onto one survivor, writing a full snapshot before anything changes. Mixed-status merges are refused, and on Pro one click restores a merge.

  Works with free FluentCRM   WP 6.4+ · PHP 8.2+   GPL-2.0

The problem

Cleaning up duplicate FluentCRM contacts by hand is a one-way door

FluentCRM has no built-in way to merge duplicate contacts. You can prevent some on import and bulk-delete filtered contacts, but merging two records into one is left to you. Do it in the admin or with raw SQL and one slip deletes the record that carried an unsubscribe, with no undo, and nothing stops you from merging a subscribed contact into someone who opted out.

delete the wrong record once, and it does not come back

Safety first

Every merge is snapshotted first, and unsafe ones are refused

This plugin is built around one rule: you should never lose a contact you did not mean to. Four checks run on every merge, on the free tier and Pro alike. One-click restore of a merge is the Pro upgrade.

Nothing changes until a snapshot is saved

Before the first record is touched, a full snapshot of every contact in the set is written to an undo journal. If that snapshot cannot be recorded, the merge aborts instead of running blind. Nothing changes until there is a recorded snapshot to restore from.

A cleanup can never re-subscribe someone who opted out

The plugin refuses to merge a subscribed contact with an unsubscribed, bounced, or complained alias. Consent stays intact, so tidying your list can never quietly resurrect a contact who asked to leave.

You never merge on a stale preview

The moment you confirm, every contact is re-read from the database and re-checked on the server. If the set no longer qualifies as a duplicate, the merge is refused rather than run on numbers that changed since you looked.

Every merge stays reachable, and reversible on Pro

Each merge is listed in a history panel. On the free tier you can confirm its snapshot exists. On Pro, one click restores it, re-creating the removed contacts and reverting the survivor. Restore brings back contact data and consent, not per-message engagement history.

How it finds them

Find duplicate contacts by email, phone, and name

No fuzzy similarity score decides what to delete. Each contact is matched exactly, after the noise is normalized away, so the sets you review are matches, not guesses. You still review every set before merging.

by email

The same inbox is caught even when the address looks different. Gmail dots and plus aliases collapse to one address, so john.doe+promo@gmail.com and johndoe@gmail.com read as the same person. Googlemail, casing, and stray whitespace are normalized too.

by phone

One number, however it was typed. Numbers are compared on their digits, so different punctuation or spacing does not hide a match. Placeholder and repeated-digit junk like 000-000-0000 is rejected and never groups unrelated people.

by name

First and last name, both required. Case-insensitive, and a single shared field is too weak to group, so two people who only share a surname are left alone. Two contacts with the same full name are grouped, so review a name-only match before you merge it.

consolidate

The survivor keeps everything worth keeping. It inherits the union of every tag and list in the set, and any custom field left empty is filled from the records being removed. Nothing useful is dropped on the way to one clean record.

Free and Pro

Start free. Add control and an undo button when the list is bigger.

The free tier does the real work: it finds duplicates, merges them with full tag, list, and field consolidation, and records a verifiable snapshot every time. Pro is what you reach for at scale, when you need to decide which contact wins and which value survives, filter a long list down to the sets you care about, merge many at once, and put any of it back with one click. One irreversible delete costs more than a year of Pro.

Free

$0forever

everything you need for a careful one-time cleanup

  • Find duplicates by email, phone, and name
  • Merge one set, with tags, lists, and empty fields consolidated onto the survivor
  • Full snapshot written before every merge
  • Mixed-status merges refused, so consent is never broken
  • Merge history with snapshot verification
Download free
14-day free trial

Pro

$49/ year · 1 site

agency: $129 / year · up to 10 sites

  • Everything in Free
  • Per-field merge: decide which value survives wherever the contacts disagree
  • Choose which contacts to merge, and which one to keep
  • Scan filters by status, name, email, phone, date, tags, lists, and custom fields
  • One-click restore of any merge from the history
  • Bulk merge many duplicate sets in one action, up to 50 per run
  • Move a removed contact's guest WooCommerce orders to the survivor
  • Updates and support
Start 14-day trial

No card for the trial · 14-day money-back guarantee · secure checkout by Freemius

Changelog

What's shipped

Version history for the plugin. Pro customers get every update automatically.

1.3.02026-07-27latest
  • Pro: per-field merge. Every standard and custom field is resolved across the set, and you are asked only where the contacts genuinely disagree.
  • Pro: choose which contacts in a set to merge, and which one to keep.
  • Pro: scan filters by status, name, email, phone, created date, tags, lists, and custom fields, applied before grouping.
  • Pro: optionally move a removed contact's guest WooCommerce orders onto the surviving contact's account.
  • Duplicate sets now collapse into an accordion, so a long scan stays readable. This is the one change on the free plan.
  • Fixed: reverting a merge could not clear a custom field it had filled in, and reported success anyway.
  • Fixed: a per-field choice was ignored for custom fields whose name is not plain ASCII.
1.2.02026-07-21
  • Merge history panel with per-row undo, so every merge, including each set from a bulk run, is reachable for restore.
  • A duplicate set is refused unless all members share one subscription status.
  • Restore re-creates a removed contact with its original subscription status.
  • Every action's result shows on the card where it happened, on both tiers.
1.1.02026-07-06
  • Pro one-click restore and Pro bulk merge.
  • Merges now re-read and re-verify each contact server side at merge time.
1.0.02026-07-05
  • Initial release: detection by normalized email, phone, and name, reversible merge with a pre-merge snapshot, and the free and Pro split.

Questions

Before you merge anything

Can I undo a merge if something goes wrong?

Yes. Before any merge, the plugin writes a full snapshot of every contact in the set to an undo journal, and if that snapshot cannot be saved, the merge does not run. On the free tier you can confirm the snapshot exists for any merge in the history panel. On Pro, one click restores a merge: it re-creates the removed contacts and reverts the survivor to its pre-merge state. Nothing is deleted until there is a recorded way back, which is the whole reason this exists instead of a bulk delete.

Will merging trigger my automations?

A merge attaches the removed contacts' tags and lists to the survivor. If you run automations that start when a tag or list is applied, treat a merge as capable of enrolling the survivor, and test on a small set first. Scanning and previewing never change data, so you can review every set safely before anything runs.

What does restore bring back, and what does it not?

Restore re-creates the removed contacts with their tags, lists, custom fields, and original subscription status, and reverts the survivor to its pre-merge state. Be clear on the limits: anything that was never part of the snapshot does not come back. Email opens, clicks, and a contact's position in a running automation are not restored, and re-created contacts are assigned new contact ids. Restore protects your contact data and consent state, not per-message engagement history.

Can a merge re-subscribe someone who opted out?

No. The plugin refuses to merge contacts that do not share one subscription status, so a subscribed contact is never merged with an unsubscribed, bounced, or complained alias. A cleanup cannot quietly move someone who opted out back into a subscribed record. Consent status is preserved on merge, and if you restore later, each re-created contact returns with the exact status it had before.

How large a list can it handle?

Single merges are fast. Bulk merge runs synchronously and is capped per run, 50 sets by default and filterable, to stay well inside PHP execution limits. For a very large cleanup, run a few bulk passes rather than one enormous batch. This keeps each run predictable instead of risking a timeout partway through.

What goes into the snapshot journal, and is that GDPR-safe?

The snapshot stores only the contact fields needed to reverse a merge, name, email, phone, tags, lists, custom fields, and subscription status, and it is kept in your own WordPress database. It is never sent anywhere else. Because the journal holds contact PII, treat it like the rest of your CRM data under your privacy policy and retention rules. It lives alongside your merge history in your database, so it stays under your control for retention and erasure, the same as any other stored contact data.

Does it need FluentCRM Pro?

No. It works with the free FluentCRM. FluentCRM just needs to be active, otherwise the plugin shows a notice and stays out of the way.

Is it GPL, and how do the trial and refund work?

Yes, it is licensed GPL-2.0-or-later. Pro is sold through Freemius. The 14-day trial does not ask for a card, and Pro comes with a 14-day money-back guarantee, so you can run a real cleanup and a real restore before you decide. The free version is available to download and stays free.

Merge your duplicates without the one-way delete.

Start Pro free for 14 days, no card required, and run a real cleanup with one-click restore if anything goes wrong. Prefer to keep it simple? The free version records a verifiable snapshot on every merge, so a careful, reviewed pass is well covered.