Something is counting your conversions more than once. This page shows you how to prove it in two minutes, which of the four causes you are looking at, and what to change for each one.
Do not start from a hunch. Open your site in a private window, open developer tools, switch to the Network tab, and type facebook.com/tr into the filter box. Reload the page. Every request you see is one pixel fire, and the query string on each one tells you exactly what was sent.
Three parameters do the work. The ev parameter is the event name, so two rows both reading ev=PageView on a single load is your duplicate, in writing. The id parameter is the pixel ID that sent it, which tells you whether you are looking at one pixel firing twice or two different pixels each firing once. And the rest of the query string shows the parameters attached, which matters because a genuine duplicate is usually identical while a legitimate second pixel often is not.
Then check the same thing from Meta's side. In Events Manager, compare the received count for a conversion event against the number of orders or leads you actually got over the same dates. If Meta reports more purchases than your backend recorded in total, that gap cannot be explained by attribution, because attribution decides which channel gets credit and never invents transactions. The Meta Pixel Helper extension is a fast second opinion for spotting a stray pixel ID on the page, but treat it as a pointer rather than as evidence, since it reads the page rather than what Meta received. Our free Meta pixel audit does the same collection across your key pages without the extension.
This is the answer most of the time. The pixel gets added through a platform integration or app, and then again through Google Tag Manager, and then again as a snippet somebody pasted into the theme or into a header injection field. Each layer was added by a different person in a different year, and none of them announced itself to the others. Both copies initialize and both fire PageView on every load, so your most common events double first and your conversion events double wherever the coverage overlaps.
The fix: pick one install layer and delete the others. Inventory before you cut: check your tag manager container, your theme or template files, any header and footer script fields, and the app or integration list on your platform, then write down every place the ID appears. Remove one layer at a time and reload with the network filter still open so you can see the count drop. Platform installs are the usual second copy, and the platform-specific hiding places are covered in the Shopify pixel audit and WooCommerce pixel audit guides.
The base code fires a PageView when it initializes. In an app built with a client-side router, teams then add their own PageView on every route change so that navigation gets tracked at all, which is correct in principle. The problem is the seam: the initial load produces one PageView from the base code, and if the router also reports that first view, or if the app redirects immediately after mount, the same view is reported again a fraction of a second later.
The fix: fire the route-change event only for navigations that happen after the first paint, and skip it on the initial load that the base code already covered. Test the routes that redirect and the ones that re-render on a query parameter change, because those are where the extra fire survives an otherwise clean fix. The same pattern applies to any event bound to a component that mounts more than once.
Running the pixel and the Conversions API together is the recommended setup, and it produces duplicates when the two channels are not linked. The browser event and the server event have to carry the same event name and the same event ID for Meta to recognize them as one action. Without that shared key, both are complete and valid, so both get counted. This one is different from the others in an important way: the network tab will show you a single browser fire and nothing looks wrong on the page at all.
The fix: generate one ID per event, use it on both channels, and confirm in Events Manager that the pair is being deduplicated rather than counted separately. The mechanics of how that key works are covered in Meta pixel vs Conversions API, so we will not repeat them here. If the server half is missing entirely rather than unmatched, that is Conversions API events not received.
Two different IDs on the page is not automatically a fault. Agencies, multi-brand businesses, and partner arrangements run parallel pixels deliberately, and each one belongs to a different ad account. The accidental version looks identical from the outside: an old ID left behind by a previous agency, a test pixel created during a rebuild, or a duplicate dataset made because someone could not find the original.
The fix: this is an ownership question, not a code question. For each ID you found in the network tab, name the ad account it reports into and the person who wanted it there. Anything you cannot account for comes out. Anything you can stays, with a note explaining why, so the next person does not delete it or duplicate it again.
Duplicates cost you twice. The reporting damage is the obvious half: inflated conversion counts and inflated revenue, which make campaigns look profitable that are not, and which stop matching your backend in a way nobody can reconcile after the fact. That side of it, along with the other reasons platform numbers drift from reality, is covered in why your ROAS numbers are wrong.
The expensive half is quieter. Meta's delivery system learns from the events it receives, so a duplicated conversion stream teaches it that certain sessions, placements, and audiences convert at a rate they do not. Those lessons are applied to how your budget is spent while the campaign runs. You cannot correct that in a spreadsheet later.
The timing matters too. Duplication is rarely a clean multiple, because the browser event fails for some share of traffic while its duplicate goes through, so the overcount moves around and there is no factor you can divide by. Fix it at the source, note the date, and treat your reporting before and after as two separate baselines.
One change at a time: remove a single install layer, reload with the network filter open, and confirm the count dropped before you touch the next one. Pulling three things at once is how a site ends up with no pixel at all and nobody sure which removal did it.
Our free Meta pixel audit is built for exactly this symptom. It loads your live pages, collects every pixel ID it can read, and flags the same ID appearing across more than one install layer, showing you which layers those are. It also reads your Google Tag Manager container, checks whether your conversion events carry the event ID keys that deduplication depends on, and flags a server-side setup running without them. That covers cause one and cause three without you opening a single template file.
It is honest about its limits. Events inside a hosted checkout, pixels running in a sandboxed app layer, and anything happening between your server and Meta cannot be read from outside, so the scan marks those as needing verification rather than guessing. Those are the ones you confirm with Test Events. The full sequence, across every platform we work on, is in the Meta pixel audit guide, and if your events are arriving thin rather than doubled, see event match quality low.
Open developer tools, go to the Network tab, filter for facebook.com/tr, and load the page fresh. Every fire is one request. Two rows with the same event name on a single load is a duplicate you can prove, and expanding each request tells you which pixel ID sent it and what parameters came along. Do this before you touch anything, because the fix depends entirely on whether the two requests carry the same ID or different ones. Reload with the filter still applied to be sure you are counting a fresh page load rather than leftovers from the previous one.
No, and this is the most expensive misunderstanding in the whole topic. Deduplication is designed to reconcile one browser event against one matching server event that shares an event name and an event ID. Two separate browser installs generate their own IDs independently, so Meta sees two legitimate events rather than one event reported twice. There is no setting that cancels them out. The only fix for a double install is removing one of the installs, and no amount of correct deduplication configuration elsewhere will compensate for leaving both in place.
Not by itself. Agencies, franchise networks, and businesses running separate campaigns for separate brands legitimately load more than one pixel on the same pages, and each one collects its own events for its own ad account. That is a design, not a defect. It becomes a problem when nobody can say why the second ID is there, when both IDs feed campaigns in the same account so the same action is optimized against twice, or when an old ID from a previous agency is still collecting quietly. The test is ownership: for each ID on your site, name the account it reports to and the person who wanted it there.
Because the app is sending its own route-change event on top of the one the base code already sent. The pixel base code fires a PageView the moment it initializes on the first real page load. If your framework then reports every client-side navigation as a virtual page view, the first navigation after load can be counted a second time, and a route change that triggers a re-render or a redirect can add more. Fire route-change events only for navigations after the initial load, and check the behaviour on the routes that redirect, since those are where the extra fire usually hides.
You can correct a report after the fact. You cannot correct the optimization. Meta's delivery system learns from the conversion events it receives, so duplicated events distort which audiences, placements, and creatives look valuable, and that distortion is applied to spending decisions in real time rather than at the end of the month. The duplication is also rarely a clean multiple, because the browser event fails for some share of traffic while the duplicate does not, so there is no correction factor you can trust. Remove the duplicate at the source and rebuild your baseline from the date it stopped.
A doubled conversion stream inflates the report and misteaches the algorithm at the same time. Scan your site in about 20 seconds to see every pixel ID and install layer we can read from outside, or have us walk it with you.