> tracking/meta-pixel-double-counting-shopify.txt
Meta Counting Your
Purchases Twice?
Meta says 80 purchases. Shopify says 40 orders. Your ROAS looks fantastic and your bank balance doesn't agree. When Meta counts every sale twice it isn't just a reporting problem, it's teaching the algorithm the wrong lesson. Here's how it happens on Shopify and how to stop it.
> symptoms.txt
Sound Familiar?
If you've landed here, you're probably seeing one of these.
- Events Manager shows roughly twice as many purchases as Shopify has online orders for the same week.
- One test order turns up as two Purchase events in Test Events, often one from the browser and one from the server, not merged.
- Purchases jumped overnight and sales didn't, usually just after a new app, tracking plugin or server-side setup went in.
- Events Manager's Diagnostics tab is grumbling about duplicate events or missing event IDs.
- The Meta Pixel Helper shows two pixel IDs, or the same one loading twice.
- Your ROAS is too good to be true. It usually is.
> quick_answer.txt
Quick Answer
Two things are reporting the same sale without a shared event ID. Usually it's the Facebook & Instagram app plus a second install: a custom pixel, an app with its own Meta option, or a separate server-side setup. Sometimes it's a pixel firing on page views of the thank you page, or an upsell app reporting its own purchase. Keep one integration in charge of both the pixel and the Conversions API, remove the rest, and check a test order arrives once.
> really_double.txt
First, Check It's Really Double Counting
Meta claiming more sales than you'd expect isn't always a duplicate. Ads Manager credits a purchase to an ad within its attribution window, by default up to 7 days after a click or 1 day after someone viewed the ad. Somebody who scrolled past your ad and then bought from a Google search counts as a Meta purchase, and Google counts the same sale too. That's two platforms claiming one order, and it's normal.
So compare raw events, not attributed results. In Events Manager, look at Purchase events received over a full week, next to Shopify's online store orders for the same week. Close means your tracking's fine and the inflation is attribution. Well above, especially near double, means read on.
Rule of thumb: Events Manager purchases should sit at or a little below your online store orders. Above is a problem. Double is a duplicate.
> cause_1.txt
1. Two Installs, Both Reporting the Sale
The one I'd bet on. The Facebook & Instagram app is sending purchases, and something else is too: a custom pixel someone pasted Meta's code into, a reviews, upsell or tracking app with its own Meta pixel option switched on, or GTM sending a Meta purchase tag. Each is working exactly as designed. There's just one too many.
On Shopify's current checkout, code in your theme can't fire a purchase, because the theme doesn't run on checkout pages. So a duplicate Purchase comes from Shopify's customer events or an app, not theme.liquid. Old theme code can still double up page views and add to carts, mind.
How to check: go to Settings, Customer events. List every app pixel and custom pixel, and open each custom pixel to see what it sends. Then go through your apps for anything with a Facebook, Meta or pixel setting. Two separate sources each sending Purchase is your answer.
How to fix: pick one owner. For most stores that's the Facebook & Instagram app. Take the Meta code out of custom pixels, switch off pixel options in other apps and remove old tracking apps you've forgotten about. If you deliberately run your own setup instead, turn off the app's customer data sharing so it isn't sending a second copy.
> cause_2.txt
2. Pixel and Conversions API Without a Shared Event ID
Running the browser pixel and the Conversions API together is the right setup. The Conversions API sends the same events from a server, where ad blockers can't touch them. Meta merges the two copies of a purchase into one, but only if they carry the same event name and the same event ID, and arrive within 48 hours of the first copy. Miss any of that and Meta counts two purchases.
The Facebook & Instagram app handles this for you at its Enhanced and Maximum data sharing levels, which both use the Conversions API. Trouble starts when the two halves come from different places, say the app's pixel and a separate server-side setup. Each makes up its own ID: one sends the order number, the other a checkout reference, or nothing. Close isn't good enough either. A prefix or a hash symbol on one side and not the other means no match.
How to check: place a test order with Test Events open. You want Purchase from the browser and the server, merged into one. Two separate Purchases, or a server copy with a different event ID, is the problem. The Diagnostics tab often flags it too.
How to fix: one system creates the event ID and both copies use it, character for character. Simplest is one integration running both the pixel and the Conversions API. If you build your own, the Shopify order ID makes a good event ID for purchases, sent in exactly the same format on both sides. More in Meta CAPI and Event Match Quality.
> cause_3.txt
3. A Purchase Fired on a Page View
Shopify's checkout_completed event fires once per checkout, which is exactly what you want for a purchase. Hand-built custom pixels sometimes do it differently. They listen for a page view and fire Purchase when the URL looks like a thank you page. That fires again on every reload, and depending on how it's written, whenever a customer comes back to check on their order.
How to check: place a test order, then refresh the thank you page and open the order status link from the confirmation email, with Test Events open. Any new Purchase means a page-view pixel.
How to fix: fire Purchase from checkout_completed only, with the order ID as the event ID so the server copy can match it.
> cause_4.txt
4. Upsell Apps Reporting Their Own Purchase
Post-purchase upsell apps move the goalposts. With an upsell page in the flow, Shopify fires checkout_completed on the first upsell page instead of the thank you page. Some upsell apps also send their own Purchase to Meta when someone takes the offer, with their own ID. Your main integration reports the order, the app reports the upsell, and Meta sees two purchases from one checkout.
How to check: look in the upsell app's settings for any Meta or pixel tracking. Then place a test order, accept the offer, and count the Purchase events in Test Events.
How to fix: in most setups I'd switch the app's own Meta tracking off and let the main integration report the order. The catch is that checkout_completed fires before the customer accepts, so the upsell's value may not be in it. Some stores live with that small undercount, others report the upsell as its own custom event rather than a second Purchase. Either is fine. Two Purchases for one checkout isn't.
> cause_5.txt
5. Late or Repeated Server Events
Custom server-side setups have a trap of their own. Meta only merges copies that arrive within 48 hours of the first. If your server sends its Purchase when Shopify marks the order paid, an order paid by bank transfer days later arrives too late to merge with the browser copy, and counts again. Retries are the other one: a server that resends after a timeout has to resend the same event ID, or Meta can't tell it's a repeat.
How to check: in your server container or the app's logs, find which Shopify event triggers the Meta purchase and how retries are handled. Compare a few event IDs and timestamps with their browser copies.
How to fix: send the server purchase when the order is created rather than when payment settles, keep the same event ID on any retry, and check your server container isn't firing Meta's tag for both a browser-forwarded event and a Shopify webhook. If that sounds like a lot, it's a good argument for server-side tracking done once, properly.
> diagnose.txt
Diagnose It in Order
Under an hour, in this order. Don't change anything until you've finished.
Compare Raw Events With Orders
Events Manager Purchase events for last full week against Shopify online store orders. Near double is a duplicate. At or below is attribution, not tracking.
List Everything That Can Send a Purchase
The Facebook & Instagram app and its data sharing level. Settings, Customer events: every app pixel and custom pixel. Apps with Meta settings. GTM and any server container.
Place a Test Order
A real order you refund afterwards, with Test Events open. Count the Purchase rows, note browser or server, and check they merge and the event IDs match.
Try to Make It Fire Again
Refresh the thank you page, open the order status link from the email, and accept an upsell if you have one. Nothing new should appear.
Use the Pixel Helper as a Clue
Two pixel IDs, or one loading twice, is worth chasing. On Shopify the sandbox can confuse it, so trust Test Events over the Pixel Helper.
Fix One Thing, Then Re-Check
One change at a time, another test order, then a week of Events Manager against Shopify. Expect reported purchases and ROAS to fall. They were inflated.
> after_the_fix.txt
What Happens After the Fix
Reported purchases drop, roughly by half if everything was doubled, and ROAS drops with them. Nothing real has changed. Warn whoever reads the reports before they panic.
Meta's delivery has been learning from doubled purchases, so give it a week or two to settle, and revisit any cost per purchase or ROAS targets set against the old numbers. Keep the same pixel. Starting a new one to get a clean slate throws away its history and makes things worse, not better.
> get_help.txt
When to Get Help
If you've found two Purchase events and can't work out where the second one comes from, or your setup mixes apps, GTM and a server container, that's what my tracking audit is for. £500, fixed, one-off. I trace every source of every purchase event, check the event IDs line up, and compare what Meta received with your actual orders. You get a written fix list and a call to walk through it. Read-only, so nothing on your store changes while I look.
And if the tracking turns out fine and it's the ads that need work, I run Facebook and Instagram ads too.
> faq.txt
Questions People Ask
The ones that come up whenever Meta's numbers look too good. If yours isn't here, just ask.
Why is Meta showing more purchases than Shopify?
Either attribution or a duplicate. Ads Manager credits sales within its attribution window, including some people who only saw an ad, so it can claim orders that also came through Google or email. That's normal. If Events Manager's raw Purchase count is well above your online store orders, something is sending each purchase twice.
Should I turn off the Conversions API to stop double counting?
No. Without it, ad blockers and iPhone privacy settings mean the browser pixel misses a chunk of your sales. The Conversions API isn't the problem, mismatched event IDs are. Run both from one integration that gives each purchase the same event ID on both sides, and Meta merges them into one.
How does Meta deduplicate pixel and Conversions API events?
It looks for two events with the same event name and the same event ID on the same pixel, arriving within 48 hours of the first one. It keeps one and drops the other. There's an older fallback that matches on browser cookie or customer ID, but it only works when the browser copy arrives first, so don't rely on it.
Can I run the Facebook & Instagram app and another tracking app together?
Only if just one of them sends events to Meta. Plenty of stores keep the app for the shop and catalogue and use a separate tool for tracking, which is fine as long as the app's data sharing is off. Two tools both sending Purchase is the most common cause of double counting I see.
Does Meta use the order number to remove duplicates?
Not by itself. Meta deduplicates on event name plus event ID. Using the Shopify order ID as the event ID for purchases is a sensible approach, because it's unique per order and both the browser and server can get hold of it. They just have to send it in exactly the same format.
Will fixing double counting hurt my Meta campaigns?
Your reported results will look worse, because they were inflated. Delivery may wobble for a week or two while it adjusts to honest numbers, and you'll need to reset any targets set against the old ones. Leaving it means Meta keeps optimising on sales that never happened, which costs more in the long run.
> ls ../tracking
More Tracking Guides
Double counting rarely travels alone.
> new_message.txt
Meta Claiming More Than You Sold?
Send me Meta's purchase count and your Shopify order count for last week. If they don't line up, I'll find out why. No hard sell, no jargon.
"Matt was really responsive throughout the whole process - no questions went unanswered and Matt was really engaged in the whole process."
Lizzie Hill · Abergele Golf Club