Tracking & Attribution

Why Does Meta Count More Purchases Than My WooCommerce Orders?

Meta showing more purchases than your WooCommerce orders? Usually two plugins send Purchase with different event ids. Find the second source and keep one.

Quick answer

Usually because two tools are sending Purchase for the same order. Meta only merges a browser and a server event when both carry the same event name and event_id, and each WooCommerce plugin makes its own ids. Run Meta for WooCommerce alongside PixelYourSite, a GTM tag or a pasted pixel and every order arrives twice. Find the second source, keep one sender per event, then check that one order produces one Purchase.

Tell us what's broken. We'll fix your tracking — free.

Describe the tracking/attribution problem you're stuck on and we'll map it to a fix: server-side conversions to Meta, Google, TikTok and Pinterest, plus first-party tracking that survives Safari. No code required.

Meta counts more purchases than your WooCommerce orders when more than one tool sends a Purchase for the same order. Meta merges duplicates only when two events share an event name and an event_id, and every plugin generates its own ids. Two senders means two Purchases per order. Find the extra sender, switch its Purchase off, and the counts line up.

The classic report on the WordPress support forums reads like this: “I placed 2 test orders and Events Manager shows 4 purchases.” That ratio, exactly two per order, is the fingerprint of two independent senders. Other causes exist, and they leave different patterns. We’ll cover how to tell them apart.

Why does Meta count one WooCommerce order twice?

Because Meta has no idea what a WooCommerce order is. It sees events. When two events arrive with the same event name and the same event_id, Meta treats them as one conversion and keeps one. When the ids differ, they are two conversions. Two plugins firing Purchase for one order send two different ids, so Meta counts two.

Meta’s deduplication rules are specific. A browser Pixel event and a server Conversions API event are merged when they carry matching event_name and event_id and arrive within 48 hours of each other. Nothing else links them. Not the order number, not the value, not the customer’s email.

Here’s how that plays out with a common WooCommerce stack:

  1. Meta for WooCommerce fires Purchase in the browser and through the Conversions API, sharing one id between the two. Meta merges them into one purchase.
  2. PixelYourSite (or a GTM tag, or a pixel pasted into the theme) fires its own Purchase with its own id. Meta counts a second purchase.
  3. If that second tool also has server-side events enabled, it merges its own pair. Still two purchases in total, one per tool.

So two test orders become four. Each tool deduplicates itself correctly. They just can’t deduplicate against each other, because neither knows the other’s id.

Diagram of one WooCommerce order sending Purchase to Meta through two tools: Meta for WooCommerce sends a browser and server Purchase sharing one event_id, which Meta merges into one; PixelYourSite sends its own Purchase with a different event_id, which Meta counts separately, so Events Manager shows two purchases for one order

How does Meta for WooCommerce avoid duplicating itself?

In its current source code, Meta for WooCommerce stores one event_id on the order (in the _meta_event_id order meta field) and reuses it for both the browser Pixel and the server event, so the pair merges. It also marks the order as tracked, separately for browser and server, and sets a 45-minute guard so parallel processes can’t fire the same Purchase twice. It’s the pattern behind picking a good event_id: one stable id per order, shared by both channels. None of that protects you from a second plugin.

What else makes Meta’s purchase count drift above real orders?

The other common causes are page reloads, unpaid orders and reporting differences. Each leaves a different pattern. Two senders give a clean 2× on every order, including test orders. Reloads and payment redirects give random extras on some orders. Unpaid orders give extras that match orders later cancelled. Attribution differences show up in Ads Manager, not in Events Manager’s raw counts.

  • The shopper lands on the thank-you page more than once. A pixel that fires on page load fires again when a shopper returns from a payment redirect or reopens the page. Plugins with a per-order guard don’t; pasted snippets and many GTM tags do.
  • Unpaid orders are counted. Meta for WooCommerce treats pending and on-hold as valid purchase states alongside processing and completed. Orders that are never paid still send a Purchase, which is why Meta counts unpaid or cancelled WooCommerce orders as purchases.
  • You’re comparing different reports. Ads Manager counts attributed purchases on the ad’s timeline, not orders on the order date. That gap is why Meta shows more conversions than your CRM and isn’t a duplicate at all.

Rule out the second sender first. It’s the most common cause, and the only one that doubles every order.

How do you find the second Purchase source on a WooCommerce store?

Place one test order and count what reaches Meta. Open Events Manager’s Test Events tool, then check the order-received page with the Meta Pixel Helper browser extension. More than one browser Purchase, or a browser and a server Purchase that don’t merge, means two senders. Then list every place a Purchase could come from and switch them off one at a time.

Work through the usual suspects:

  1. Plugins. In WordPress → Plugins, look for more than one of: Meta for WooCommerce (formerly Facebook for WooCommerce), PixelYourSite, Pixel Manager for WooCommerce, or any “conversion tracking” plugin with a Meta setting. Page builders and theme bundles sometimes include a pixel field too.
  2. Google Tag Manager. Open your container and search for tags that load the Meta Pixel or call fbq('track', 'Purchase'). A GTM Purchase tag plus a plugin is a two-sender setup.
  3. Hard-coded snippets. View the source of your order-received page and search for Purchase. A snippet in the theme’s header, footer or a code-snippets plugin counts as a sender.
  4. Server-side tools. A server container (Stape or your own server-side GTM), a hosting-level Conversions API feature, or a separate CAPI app each send their own server Purchase with their own id.
  5. Test. Disable the suspect, place another order, and confirm Test Events shows one Purchase, or one merged browser-and-server pair.

When you remove a tool, keep Meta’s base pixel on the site through whichever tool stays. The base code sets the _fbp browser cookie, and server events match better when they carry it.

Can you make two plugins deduplicate each other?

Only if both send the same event_id for the same order, and off-the-shelf plugins don’t coordinate that. Each generates its own id, and none reads another plugin’s. You’d need custom code to force a shared id. The reliable fix is to keep one source per event: one tool owns Purchase, and every other tool has its Purchase switched off.

That doesn’t mean one tool for everything. It’s fine to run one plugin for browse events and another for Purchase, as long as no event name is sent by both. Write down which tool owns ViewContent, AddToCart, InitiateCheckout and Purchase. Two owners for any one event means that event double counts.

A useful check once you’ve settled on an owner: over a full week, Events Manager’s Purchase count should sit close to your paid orders (Processing plus Completed) for the same days. It won’t match exactly, since time zones and late payments shift a few orders, but it shouldn’t run at twice your volume.

How does PartialLeads keep Meta’s purchase count equal to your paid orders?

PartialLeads sends exactly one server-side Purchase to Meta per paid WooCommerce order, with an event_id built from the order itself, so retries and redelivered webhooks can never add a second one. Nothing fires on the thank-you page. The PartialLeads side is one sender by design. Your job is making sure it’s the only Purchase sender.

Where the Purchase comes from. The Purchase is owned by WooCommerce’s order webhooks, not a page load. PartialLeads sends it when an order reaches Processing or Completed; pending, on-hold, failed and cancelled orders are not sent. Reloading the order-received page, or returning from a payment redirect, sends nothing.

Why it can’t double-send. Each event_id is deterministic: a SHA-256 hash of the pixel id, the event name and the order record. The dispatch table is unique on that id, so a webhook WooCommerce delivers twice, or a retry after a network error, can’t produce a second Purchase. The value is the full order total including tax and shipping, after discounts, recorded once.

What else it sends. The PartialLeads WooCommerce plugin forwards view product, add to cart and begin checkout server-side to Meta, Pinterest and TikTok. The same paid order goes as a Purchase to each connected platform, and as a row in the Google Sheet you import into Google Ads.

PartialLeads dashboard for one week of WooCommerce orders: the Purchases ledger lists each paid order with its total and matched source, and the Meta CAPI activity log beside it shows exactly one Purchase per order with its event_id and a green sent status, and KPI tiles showing 120 paid orders, 120 purchases sent and none failed

Where you see it working. The Purchases ledger lists every paid order with its value and matched source; its count for a week should equal your Processing plus Completed orders. The Meta CAPI activity log shows each Purchase sent, with its status, so you can compare it line by line against Events Manager. On the Leads list, the API column shows which conversion APIs each buyer was sent to. If Events Manager shows more Purchases than the activity log, the extras came from somewhere else.

The honest constraints. PartialLeads’ event ids are its own. It never double-sends, but it does not deduplicate against another plugin’s Purchase: if Meta for WooCommerce or PixelYourSite still sends Purchase, Meta counts both. Switch their Purchase off, or the pixel plugin entirely, while keeping Meta’s base pixel for the _fbp cookie. A paid order edited later isn’t re-sent. WooCommerce Subscriptions renewals are recorded but not sent. PartialLeads controls what’s sent; how Meta matches and attributes it is Meta’s half. The full setup is in the guide to tracking WooCommerce purchases server-side to Meta.

What breaks The mechanism Where you see it in the dashboard
Two plugins each send Purchase One server-side Purchase per paid order; switch the other tool’s Purchase off Meta CAPI activity log vs Events Manager
Webhook redelivered or retried Deterministic event_id, unique per order in the dispatch table Meta CAPI activity log
Thank-you page reload or payment redirect Purchase comes from order webhooks, not a page load Purchases ledger
Unpaid orders counted Sent only at Processing or Completed Purchases ledger count vs paid orders
Unsure which tool sent a Purchase Per-lead record of every API a buyer was sent to Leads list, API column

Tell us what's broken. We'll fix your tracking — free.

Describe the tracking/attribution problem you're stuck on and we'll map it to a fix: server-side conversions to Meta, Google, TikTok and Pinterest, plus first-party tracking that survives Safari. No code required.

Sources


Frequently asked questions

QWhy does Events Manager show two purchases for every WooCommerce test order?
Almost always because two tools are sending Purchase, each with its own event_id. Meta merges events only when the event name and event_id match, so it counts one purchase per tool. A clean two-to-one ratio on every order points to two senders rather than page reloads or unpaid orders.
QCan I run Meta for WooCommerce and PixelYourSite at the same time?
You can, but not with both sending the same events. Each plugin deduplicates its own browser and server events, not the other's. Pick one plugin to own Purchase and switch Purchase off in the other, or remove one plugin completely. Then place a test order and confirm Events Manager shows a single Purchase.
QDoes sending both the Pixel and the Conversions API double count purchases?
Not when both come from the same tool and share an event_id. Meta merges a browser and a server event with the same event name and event_id that arrive within 48 hours. Double counting happens when the two events carry different ids, which is what you get when they come from different tools.
QWill Meta remove the duplicate purchases it already counted?
No. Fixing your setup stops new duplicates, but purchases Meta already received stay in your history. Expect inflated purchase counts and ROAS for the affected dates, and compare campaigns on data from after the fix. Sending extra events to "cancel" old ones only adds more events.
QHow do I check that my fix worked?
Place one real test order and watch Events Manager's Test Events tool: you should see one Purchase, or one browser and one server Purchase marked as deduplicated. Then compare a full week of Purchase events against your Processing and Completed orders for the same days. They should be close, not double.
QDoes PartialLeads deduplicate against my existing pixel plugin?
No. PartialLeads never sends the same Purchase twice, but its event ids are its own, so it can't merge with another plugin's Purchase. If you add PartialLeads for purchases, switch off Purchase in your other plugin and keep Meta's base pixel on the site so the _fbp cookie is still set.

Find the qualified leads your forms are currently throwing away.

Install PartialLeads on one landing page, send traffic, and compare what your CRM captured against what PartialLeads recovered and qualified.