Skip to content
bizurk
← ALL WRITING

2026-04-17 (Updated 2026-10-23) / 11 MIN READ

Reconciling GA4, Meta, and Shopify purchase counts

The short, full, and nuanced answer on ga4 meta shopify reconciliation. Five sources of variance and the one number to trust per question asked.

"My GA4 purchase count does not match Shopify, and neither of them matches Meta. Who is right?"

I hear this question at least once a month from DTC operators. The answer is all of them and none of them, depending on which question you are trying to answer. Each platform is counting something slightly different, and a healthy analytics stack shows some variance between them. The totals alone do not establish whether the implementation is working.

This is the short and full answer on ga4 meta shopify reconciliation, drawn from a multi-platform analytics engine I shipped earlier this year where this exact variance was the first thing the CEO and ops lead noticed.

The short answer

Use the Shopify order ledger for the defined order population, GA4 for observed or modeled web activity, and Meta for ad attributed results under its report settings.

Differences are common because the populations and counting rules differ. The behavior of those differences is worth watching.

The fuller answer: what each platform actually counts

GA4, Meta, and Shopify are three different tools measuring three overlapping slices of the same commercial reality. Shopify reports orders that completed. Meta reports conversions the ad algorithm is willing to attribute to ad exposures. GA4 reports purchase events from sessions it managed to cookie. They rarely agree on the denominator, let alone the numerator.

Shopify is the closest thing to ground truth. It counts every completed order, including POS, wholesale channels, B2B, draft orders manually converted, and subscription rebills from Recharge or Bold. It carries no attribution and no filtering. If the order processed a payment, Shopify counted it.

GA4 counts purchase events from web sessions it could observe. Cookie loss matters a lot here. An iPhone user in Safari who cleared their ITP-gated cookies between the ad click and the purchase will show up in Shopify but not in GA4's attribution model. GA4 also filters bot traffic and obeys consent-mode gating, so numbers move around quietly as consent rates shift.

Meta attributes conversions using the report's selected window and settings. Record those settings with the export, since GA4 can assign credit differently. A report total from either platform can be higher or lower depending on the configuration and collection available.

Map the events behind the disagreement before changing tags. The inventory gives each platform count a corresponding event and owner.

A solitary tower rising from a distant ridge under a soft horizon, the scale of the structure dwarfed by surrounding terrain.

Five sources of variance

Every ga4 meta shopify reconciliation I have run decomposed the disagreement into some mix of these five sources.

Collection and filtering. Consent settings affect what GA4 can observe and model, while each system can filter or process activity differently. Inspect the actual configuration and exported order population before assigning the gap to consent or bots.

Attribution window mismatch. Record the actual attribution model and lookback settings used by each report. Compare ad attributed purchases with the same question in mind. A total purchase event report and a channel attribution report can answer different questions even inside one platform.

POS, draft orders, and non-web commerce in Shopify. Shopify totals include orders that never touched your website. If you run POS at retail events or have a B2B channel placing draft orders, those show up in Shopify totals but never appear in GA4 or Meta. Filter them out before comparing.

Dedup failures. A deduplication fault can inflate received purchase events, with the size depending on which events are duplicated. If the browser pixel and the server event disagree on event_id, Meta counts both. I covered the fix in the event_id strategy across Shopify Pixel, CAPI, and GTM. A dedup failure looks exactly like an attribution problem until you grep the payloads.

Get the CAPI Leak Report for a diagnostic focused on Meta event delivery and deduplication. That scope fits the branch where the investigation points to a faulty Meta setup.

Currency and refund handling. Shopify reports gross order value in store currency. GA4 reports purchase_value based on what the event sent. Meta reports conversion value in the ad account currency. If any of these do not agree on decimal handling, the currency conversion rate at event time, or whether refunds have been offset, you will see percentage-scale disagreement that looks like a data bug and is actually a bookkeeping artifact.

Macro detail of the tower's stonework, weathered surface texture filling the frame.

When discrepancy is a bug versus a feature

A discrepancy becomes worth investigating when its definition is unclear or its behavior changes. There is no universal percentage that proves a stack is healthy. Channel mix, consent choices, refunds, renewals, reporting delays, and attribution settings all affect the result.

An exact match can happen, especially with small samples or deliberately aligned reporting. A mismatch can be legitimate. Establish a baseline for the same populations, then investigate a step change or an event level inconsistency.

A real attribution audit walkthrough follows a reported gap through the investigation. Use it to see the evidence needed beyond an initial percentage comparison.

Seven steps for the first reconciliation

The first pass needs a dated record of the assumptions as much as a spreadsheet. Keep the raw exports alongside the comparison so someone can repeat it.

1. Set the comparison window

Choose a completed reporting period and write down the start, end, timezone, and extraction time. A quiet thirty day period is a useful starting point. Processing delays and attribution windows depend on the report, so confirm those settings rather than assuming every number is final on the same day.

2. Export the Shopify orders first

Start with a defined set of paid orders. Record how POS, wholesale, test orders, refunds, and subscription renewals are handled. The filter below is an example for a web acquisition comparison, rather than the definition of total company revenue.

Export: Orders
Date range: 2026-03-24 00:00 UTC to 2026-04-23 00:00 UTC
Financial status: paid
Source name: web
Fulfillment status: any

Keep order_id, order_number, created_at, total_price, currency, source_name, and customer_id. Preserve the original timestamp and derive a separate comparison date in the chosen timezone. Use a consistent revenue definition, including an explicit policy for shipping, tax, discounts, and refunds.

3. Pull GA4 for the same dates

Use a saved report or the Data API and retain the request. The API example uses ecommercePurchases and purchaseRevenue; check the current schema and response metadata for the property before using it. An API response still needs inspection for thresholding, sampling, or other reporting restrictions.

const request = {
  property: "properties/XXXXXXXXX",
  dimensions: [{ name: "date" }],
  metrics: [
    { name: "ecommercePurchases" },
    { name: "purchaseRevenue" },
    { name: "totalUsers" },
  ],
  dateRanges: [{ startDate: "2026-03-24", endDate: "2026-04-22" }],
};

Keep transaction identifiers where your export supports them. A daily aggregate locates a change; an order or transaction level comparison helps investigate it. Record the channel attribution settings separately from the total purchase event count.

4. Pull the Meta report with its settings attached

Export purchase actions, purchase values, spend, and report dates from Ads Insights. Save the attribution setting and reporting timezone with the export. Those settings affect the comparison, and an ad attributed purchase is a different population from all paid Shopify orders.

Endpoint: /act_ACCOUNT_ID/insights
Fields: actions, action_values, impressions, clicks, spend
Date range: match the comparison period
Attribution: record the setting used by this account and report
Breakdown: campaign where needed for the investigation

5. Compare counts and values separately

Join the daily aggregates on the normalized comparison date. A query like this makes the direction of a gap visible. The source models must already apply the same date, order, and currency policies.

SELECT
  date,
  shopify_orders,
  ga4_purchases,
  meta_purchases,
  ROUND(100.0 * SAFE_DIVIDE(shopify_orders - ga4_purchases, shopify_orders), 1)
    AS ga4_gap_pct,
  ROUND(100.0 * SAFE_DIVIDE(shopify_orders - meta_purchases, shopify_orders), 1)
    AS meta_gap_pct
FROM `project.marts.daily_reconciliation`
WHERE date BETWEEN '2026-03-24' AND '2026-04-22'
ORDER BY date;

For multiple currencies, convert to one base currency using the order's recorded ledger rate. A current spot rate applied months later creates a new difference that can look like a tracking fault. Compare revenue only after currency and refund treatment agree.

6. Find the date the gap changed

Plot the daily gap over a longer baseline, such as ninety days. A stable difference that suddenly widens is more useful than a single large percentage. Put the change date beside the release history, consent banner changes, tag publications, and platform incidents. That narrows the investigation to something a person can check.

7. Test the likely cause and repeat the pull

Inspect missing or repeated events, consent state, source filters, currency handling, and attribution settings against the evidence. An unexpectedly high Meta count warrants checking deduplication, but the total alone does not establish the cause. Keep the original exports, record the change, and repeat the same comparison after the relevant reporting delay.

Once the definitions hold, make the reconciliation a scheduled model with saved assumptions and alerts based on your own baseline. The dbt purchase reconciliation model is the implementation sequel. It covers the recurring comparison after this first diagnostic pass.

If your numbers agree suspiciously well, dedup is often the culprit. The debugging postmortem on CAPI payload mismatch covers the single most common failure mode that makes this reconciliation look clean when it is not.

If the variance feels seasonal or keeps widening, attribution windows are doing it. I laid out the current window behavior on iOS and Android privacy in the field notes on attribution windows after iOS and Android privacy updates.

For the full CAPI context, start with the field guide to Meta CAPI for DTC operators. Most reconciliation problems are downstream of a CAPI configuration choice.

For a written investigation across the event map and platform reports, the Attribution Teardown covers that broader diagnostic scope.

Close perspective on the tower's pointed roof, geometric form set against a quiet sky.

FAQ

Which platform should I report to the board as my 'real' revenue?

Shopify. It is the only platform that reports completed transactions; the others report models of completed transactions. GA4 and Meta numbers belong on marketing dashboards, not on the P&L.

How much variance is too much?

Start with matching definitions and a baseline from the store. A changing gap or missing transaction deserves investigation; a fixed percentage alone cannot certify the setup.

Why does Meta sometimes report more conversions than Shopify?

Check report definitions, attribution settings, dates, and browser and server duplicates. Inspect the event identifiers before deciding that deduplication is the cause.

Should I change my attribution windows to make the numbers match?

No. Change windows only when the window genuinely misrepresents the customer journey, not to improve visual alignment on a dashboard. Matching windows between platforms is a reasonable exercise for like-for-like comparison, but aligning windows to hide a broken implementation is a common way to ship worse attribution.

How often should I run this reconciliation?

Monthly at minimum, weekly if the brand is spending seven figures per year on Meta. A silent variance drift is the earliest signal that something shifted in the tracking stack, often before the symptoms show up on ROAS dashboards. A quarterly reconciliation is reactive; monthly catches problems before they cost a full budget cycle.

The tower reduced to a clean silhouette against a backlit sky, form prioritized over detail.

Sources and specifics

The workflow combines the original forensic reconciliation notes with the purchase count explanation. Its example dates and schema names are illustrative.

The GA4 Data API schema defines the available dimensions and metrics. Use the Meta Ads Insights documentation for the fields and reporting options in your account. The earlier articles' variance percentages were observations without a retained public benchmark, so this guide uses explicit definitions and a store specific baseline instead.

// related

Let us talk

If something in here connected, feel free to reach out. No pitch deck, no intake form. Just a direct conversation.

>Get in touch

Tell me what you’re trying to ship.

Send a quick message and I read it within a day, or talk to AI Michael first if you want to feel out your project before you write to me.

By sending this, you agree to the Terms and acknowledge the Privacy Policy.