Admaxxer is a DTC analytics platform with built-in Meta + Google ad ops. If Meta Ads Manager claims 142 purchases today but Shopify shows 97 paid orders, you are not going crazy — the two systems are measuring different things. The short answer: Meta reports modelled, 7-day-click-attributed purchases bucketed by *ad impression time*; Shopify reports deterministic last-click orders bucketed by *order creation time*, and the two will never agree unless CAPI deduplication is perfect and the windows are aligned.
## TL;DR
- Meta defaults to 7d click + 1d view attribution; Shopify's native reports are last-click by checkout time
- CAPI without a shared `event_id` double-counts purchases (browser pixel + server)
- iOS 14.5 + ATT means 20–40% of iOS purchases arrive modelled, not observed
- Test orders, abandoned checkouts that later convert, and partial refunds each skew one side
- The fix is not to force them to match — it's to pick one source of truth (we recommend Shopify paid orders) and reconcile Meta's contribution using the blended MER tile
## Attribution windows are different by default
Meta's default attribution window is 7-day click + 1-day view. A shopper who clicks your ad on Monday, browses three competitors, and buys on Friday is still a "Meta purchase" in Ads Manager. Shopify, meanwhile, reports that order under whichever source the `ref=` parameter or last-click UTM said — often direct, or the email campaign they opened Thursday night. Neither system is lying; they're answering different questions. Meta answers "did my ad cause the click that eventually led to a purchase?" and Shopify answers "what was the last referrer before checkout?"
On top of that, Meta buckets by the *time of impression*, not the time of purchase. If someone saw an ad on April 10 and bought on April 18, Meta attributes that purchase to April 10 spend. Shopify attributes it to April 18 revenue. Your daily tiles will never line up unless you roll up to a full attribution window (e.g. weekly spend vs. weekly revenue).
## CAPI deduplication and event_id
The Conversions API (CAPI) is a server-to-server purchase signal. If you fire the browser Purchase pixel *and* the server CAPI Purchase without a shared `event_id`, Meta sees two distinct events and counts both. Admaxxer's [CAPI match rate tile](/docs/capi-match-rate) shows the percentage of server events that matched a browser event via `event_id` — if that number is under 85%, duplicates are almost certainly inflating your purchase count.
Deduplication works like this: Meta holds each incoming event for up to 48 hours, waiting for its twin. If a `event_id` hash matches across pixel and CAPI within that window, the two collapse to one. If the browser event never fires (ad-blocker, slow hydration, fast checkout redirect), the server event stands alone. If neither side sends `event_id`, both count. On well-instrumented stores, match rate lives in the 90–98% range; on stores that retrofit CAPI without wiring event_id on the pixel, it can sit below 60%.
## Diagnostic steps
### Step 1: Pull the CAPI match rate for the date range in question
Open the Admaxxer dashboard, go to **Connections → Meta → CAPI health**, and read the match rate for the 7-day window that covers the discrepancy. If it's under 85%, stop here and fix deduplication before anything else.
### Step 2: Compare Meta's "Purchases" column to Shopify's "Orders" column at the weekly level
Meta's daily tiles bucket by impression time; Shopify's bucket by order time. Weekly rollups smooth this. Use the Admaxxer [Blended MER tile](/docs/metrics/mer) which already normalises both to order time.
### Step 3: Filter out test orders and draft orders from Shopify
Shopify's native orders report includes `is_test=true` and draft orders by default. Meta never sees these (no pixel fire on a bogus checkout). If your team tests five orders a day, that's 150/month of silent inflation on Shopify.
### Step 4: Check the attribution window on Meta
Ads Manager → Columns → Customize → Comparing Windows. Set it to 1-day click to see the deterministic last-click equivalent. That's the number you can actually compare to Shopify's last-click report.
### Step 5: Check for partial refunds and store credit
Meta never sees refunds. If 8% of orders are refunded in the 30 days after purchase, Meta's revenue number is ~8% overstated relative to net Shopify revenue.
## iOS 14.5 and post-privacy modelling
Since April 2021, iOS users who decline App Tracking Transparency (80%+ opt-out on average) don't generate deterministic pixel fires that Meta can tie back to an ad. Meta fills this gap with *modelled conversions* — statistical estimates based on aggregated patterns. These are real purchases (they happened), but they're attributed via model, not observation. Modelled conversions tend to over-attribute to Meta's largest campaigns and under-attribute to narrow or new ones. If you see Meta claim 40 purchases on a campaign that Shopify says drove 22 via UTMs, some of the gap is likely modelled conversions — real purchases that *might* have been Meta-driven.
## Common mistakes
Three patterns we see regularly on new Admaxxer onboardings:
1. **Sending both Purchase and CompletedCheckout from CAPI.** Shopify fires both. Meta treats `CompletedCheckout` as a distinct event, so your purchase count doubles when someone maps both to the `Purchase` event by accident.
2. **Firing Purchase from a thank-you page that is hit on every order confirmation email click.** If users click their email receipt, the pixel refires, and Meta counts a second purchase. Always guard the pixel with a session flag or fire from CAPI only.
3. **Currency mismatch.** Shopify stores in shop currency; Meta receives the `currency` field and converts to the ad account's currency at the time of event. Exchange-rate drift over 7 days can produce 3–5% revenue mismatches on non-USD stores.
For a deeper fix plan, see the Admaxxer guides on [Platform vs pixel conversions](/guides/platform-vs-pixel-conversions) and [Blended MER vs ROAS](/guides/blended-mer-vs-roas), or ask the Claude agent via [query_metrics](/docs/ai-agent) for a reconciliation report.
## FAQs
**How long does CAPI deduplication take?**
Meta holds events for up to 48 hours, waiting for the matching `event_id` from the other side. If neither twin arrives within that window, deduplication fails and both events count.
**Does this apply to Klaviyo revenue too?**
Yes — if Klaviyo fires its own Purchase event via pixel, and Shopify also fires Purchase via CAPI, and both use different `event_id` formats, you'll double-count. Standardise on one source (Shopify webhooks → CAPI) and let Klaviyo use email attribution only.
**Can the Admaxxer AI agent reconcile this automatically?**
The [Claude agent's](/docs/ai-agent) `query_metrics` tool pulls Meta purchases and Shopify orders in the same query and flags discrepancies over 15%. It will not automatically fix deduplication, but it will point you to the specific campaign where the gap is widest.
**What if my CAPI match rate is 100%?**
Then deduplication is fine — your discrepancy is attribution window, modelled conversions, or refunds. Start with the window check.
**Should I switch to 1-day-click attribution?**
For most DTC stores with consideration cycles under 3 days, yes. See our [1-day vs 7-day click attribution guide](/guides/1-day-vs-7-day-click-attribution) for the math.
Frequently Asked Questions
How long does CAPI deduplication take?
Meta holds events for up to 48 hours waiting for the matching event_id from the other side. If neither twin arrives within that window, deduplication fails and both events count.
Does this apply to Klaviyo revenue too?
Yes — if Klaviyo fires its own Purchase event via pixel and Shopify also fires Purchase via CAPI with different event_id formats, you'll double-count. Standardise on one source (Shopify webhooks → CAPI) and let Klaviyo handle email attribution only.
Can the Admaxxer AI agent reconcile this automatically?
The Claude agent's query_metrics tool pulls Meta purchases and Shopify orders in the same query and flags discrepancies over 15%. It will not auto-fix deduplication but points you to the specific campaign where the gap is widest.
What if my CAPI match rate is 100%?
Then deduplication is fine — your discrepancy is attribution window, modelled conversions, or refunds. Start with the attribution window check.
Should I switch to 1-day-click attribution?
For most DTC stores with consideration cycles under 3 days, yes. See our 1-day vs 7-day click attribution guide for the math.
Put This Knowledge Into Action
Bring Meta and Google ads into one self-hosted workspace.