Meta conversion tracking end to end: pixel, CAPI, and events that dedup

Meta conversion tracking is one pipeline, not three products. Install the pixel, add the Conversions API on whichever of three paths fits your stack, and make sure Meta counts each sale once instead of twice. Includes the four reasons that count quietly doubles.

Kay Vink
Kay Vink

You turn on the Conversions API and your Meta conversions jump overnight. The ads didn't get better: every purchase is now counted twice, once from the browser pixel and once from your server, and nothing is telling Meta they're the same sale. Meta conversion tracking is really one pipeline with three layers: the pixel (browser events), the Conversions API (CAPI) (the same events from your server), and the shared event_id + event_name that lets Meta collapse the pair into one count. Skip a layer and you either lose signal or double it.

The advice you'll usually find covers one layer at a time: a pixel install here, a CAPI integration there, a one-line "remember to dedup." But you're not assembling three products, you're honoring one contract, and the contract is the only place it breaks. This guide runs the pipeline end to end, then spends its best sections on the layer that actually fails: getting the two transports to match.

#The three layers, one pipeline

The pixel and CAPI are redundant transports for the same events, and that redundancy is deliberate. Browsers running ITP, ad blockers, and consent-restricted sessions drop pixel events; server events don't have that problem but lack browser context. Meta's answer is: send both, tag both with the same event_id, and let Events Manager collapse them.

#Layer 1: install the Meta pixel

The pixel is the browser half: the base code sitewide, standard events (Purchase, Lead, CompleteRegistration) on the moments that matter, with value and currency on anything money-shaped. Install directly or via GTM; on Shopify, use the native integration rather than pasting code (the store-specific path is Shopify pixel setup: native web pixels and the Meta Pixel, done right). What the pixel is (and its post-cookie limits) gets full treatment in The Meta Pixel: what it is, what it sees, where to find your ID; what matters here is one rule: every event you'll also send server-side must carry an eventID from the moment it fires. Retrofitting IDs later means a window of double counting.

#Layer 2: stand up CAPI on one of three realistic paths

Pick by who maintains it, because CAPI is infrastructure, not a checkbox:

  1. Partner integration (Shopify, WooCommerce, and other platform-native CAPI). Least control, least maintenance, dedup handled for you: the correct default for standard ecom stacks.
  2. Server-side GTM: your own tagging server forwards events to Meta, so you get full control over what's sent and one place to manage every platform. Setup and tradeoffs live in Server-side tagging with sGTM: setup, costs, and when it's not worth it.
  3. Direct API integration: your backend calls the Conversions API. Maximum control and the only path that cleanly sends CRM-stage events, at the cost of owning the code.

If you're still deciding whether CAPI is worth standing up at all, Conversions API vs the Meta Pixel: what actually changes is the decision page; the short version is that "pixel or CAPI" is the wrong question. The choice is which CAPI path, not whether.

#Layer 3: dedup, the contract and the four ways it breaks

Dedup is exact-match on two fields: when a browser event and a server event arrive with the same event_name and the same event_id, Meta keeps one, per its deduplication documentation. No match, no dedup, and every miss inflates your conversions. Running Buron's first-party pixel alongside Meta's, these are the four misses we actually hit:

  1. Missing event_id on one side. The pixel fires with an ID, the server event ships without one (or vice versa). Both count. Detection: Events Manager → your event → the dedup/"event overlap" view, where server events should show as deduplicated against browser events.
  2. Mismatched ID formats or casing. Order-1234 vs order-1234, a UUID regenerated per transport instead of shared. Exact string match means "almost identical" is "different". Detection: Test Events tool, fire one conversion and read both raw payloads side by side.
  3. Late server events. The server batch lands hours later (queue backlog, cron cadence); dedup works within Meta's matching window, but late-arriving events degrade matching and make daily counts wobble, and events later than the window count separately. Detection: compare event timestamps browser-vs-server in Test Events; keep server sends near-real-time.
  4. Missing browser event. The pixel is consent-blocked or ad-blocked, so the server event stands alone. That's dedup working as designed (CAPI recovering signal), but if you expected both, your pixel-based numbers (and any platform comparing against them) drift. Detection: browser/server event ratio per event in Events Manager; sudden ratio shifts mean a banner or blocker change, not a sales change.

#Verify in Events Manager

Verification is three surfaces, in order. Test Events: fire a conversion with the test code active and watch both events arrive with matching IDs. The event detail view: deduplication status healthy, browser/server overlap where you expect it, and EMQ (event match quality) not sitting in the red. Low EMQ means your server events are shipping without enough hashed customer parameters. Ads Manager sanity: conversion counts within a plausible band of your store or CRM truth. If Meta and Shopify disagree hard, that has its own diagnosis in Why Facebook Ads conversions don't match Shopify, and the recurring version of all these checks is The conversion tracking QA checklist: test it like you'd test code.

Here's the part the setup guides leave out: dedup isn't a launch-day property. It holds the day you verify it, then drifts the next time a theme changes, a consent banner updates, or an app regenerates IDs. And it drifts silently. The break has an unmistakable shape (illustrative numbers): browser/server pairing holding around 95% for months, then dropping to 60% overnight the day a theme update ships, while both individual event counts still look perfectly healthy. Nothing in Events Manager waves a flag, because nothing there is technically broken.

Which is exactly why verifying dedup once isn't the finish line. The hard part is catching the day it silently slips, and that's the part worth handing off. Buron runs a first-party pixel next to Meta's and watches the browser/server/order ratios continuously, so the day the pairing drops you get a dated finding instead of three weeks of double-counted conversions steering Advantage+. [Connect your store →]

Frequently asked questions

Why is Meta counting my conversions twice?

Almost always a deduplication miss: the pixel and the Conversions API both report the same purchase, but the two events don't carry a matching event_id and event_name, so Meta counts them as two conversions. Fix the IDs so both sides send identical values, then confirm the dedup status in Events Manager.

Do I need both the Meta pixel and the Conversions API?

Yes: they're layers, not alternatives. The pixel captures browser context and covers users the server path can't see; CAPI recovers the events browsers block or drop and improves match quality. Meta's guidance and observed delivery both favor running both with deduplication, not choosing one.

What is event match quality (EMQ) in Events Manager?

A 0 to 10 score per event estimating how well the customer information you send (hashed email, phone, click ID like fbclid/fbp) lets Meta match events to accounts. Higher EMQ means more attributed conversions and better optimization; raising it means sending more, and better-formatted, matching parameters server-side.

Related