Why your GA4 numbers don't match your ad spend (and how to join them)

GA4 says 1,200 conversions last month. Meta Ads Manager says 847. Google Ads says 1,310. Your database says 962 orders actually shipped.

Which one is right?

None of them, and that's not the point. They're each measuring something different, on different rules, with different blind spots. Trying to "reconcile" them into one number is a trap. The right move is to stop reconciling and start joining.

Why the numbers differ

Four reasons, each independent:

1. Different attribution models. GA4 uses data-driven attribution across your channels. Meta uses its own click- and view-based windows. Google Ads uses last-click by default. The same purchase gets credited to a different channel in each system.

2. Different conversion definitions. Your GA4 "conversion" might be a purchase event. Meta's might be a pixel fire on the same page — or a Lead event you set up differently. Google Ads counts a conversion when its tag fires, which may or may not align with either. Three systems, three definitions of "a conversion."

3. Different windows. A buyer who clicked a Meta ad, then came back via organic search a week later and bought: GA4 might credit organic (last non-direct), Meta might credit itself (within window), Google Ads credits nothing. Same transaction, three verdicts.

4. Consent mode and sampling. GA4 under consent mode models some behavior; without it, it undercounts. Meta's signal shrinks under iOS restrictions. Google Ads is the most literal. The gaps aren't symmetric.

You will not make these agree. You don't need to.

Stop reconciling, start joining

Reconciliation asks "which number is true?" Joining asks "what actually happened, by buyer?" The second question is answerable; the first isn't.

Joining means taking three streams and keying them on identity instead of on each platform's attribution:

  • Spend — dollars out to Meta and Google, by campaign and day, from the ad platforms.

  • Traffic and events — sessions, page views, and the funnel events that matter (add-to-cart, checkout, purchase), from GA4.

  • Revenue — the orders that actually happened, from your database, tied to the buyer.

The join key is the identity you captured at first touch — a gclid for Google Ads, a utm pair for Meta (or a fbclid resolved back to the campaign), carried through the session and matched to the customer at the order. When a buyer who first arrived on a paid click places an order, you know which spend acquired them, regardless of what any platform's attribution window says.

This is the only honest way to answer "did the spend pay back" — and it's the thing FunnelKeeper is built to do.

What to actually capture

If you're building this yourself, the minimum viable join is:

  1. Capture first-touch attribution on every session. utm_source, utm_medium, utm_campaign, and gclid/fbclid stored against the user or session before anything else overwrites them. First touch is the one you can't recover later.

  2. Capture last-touch too. The channel that closed the sale matters for optimization; first touch matters for payback. Keep both.

  3. Fire a real conversion event with the order id. Not a "page view of the thank-you page" — an event that carries the transaction id and value, so it can be matched to the database row.

  4. Resolve identity to the customer. Email is the most reliable key. A buyer who buys twice should be one customer, not two.

  5. Store it all append-only. Corrections are new rows, not overwrites. You'll thank yourself when a number looks wrong and you need to see what it was before.

Why this is better than picking a number

When you join instead of reconcile, three things get easier:

  • Unattributed revenue becomes visible. Orders that don't trace to any paid click show up as their own category instead of being smeared across channels to make the totals balance. That's the most honest line on the whole report.

  • Payback becomes computable per channel. Spend in, gross profit out, by the channel that acquired the customer — see ROAS vs. payback period.

  • The platforms stop being the source of truth. They become inputs. Your database is the source of truth, because that's where the money actually is.

FAQ

Which platform's number should I trust? None of them as the answer. Trust your database for revenue, the ad platforms for spend, and GA4 for traffic. Join them; don't average them.

Do I still need GA4 if I'm joining to my database? Yes — GA4 gives you the traffic and funnel-event grain (sessions, add-to-cart, checkout) that your database doesn't have. The join is what makes both useful.

What about server-side tagging / consent mode v2? They help GA4 count more accurately under consent restrictions, and they're worth setting up. They don't replace the join — they just make one of the three streams less lossy.