Why Meta Ads purchases vanish in GA4: the in-app browser

17 minutes read

Meta Ads Manager says your campaign drove 47 purchases this week. You open GA4, filter to facebook / cpc and instagram / cpc, look at the same date range: 12 transactions. The other 35 are sitting in (direct) / (none) or under a mollie.com / referral row that didn’t exist a month ago.

Nothing’s broken in your tags. The gap is a structural problem with how Meta opens links, how payment providers behave on mobile, and how GA4 reads cookies.

Here’s what actually happens, and the handful of fixes that genuinely help versus the ones that look like they should but don’t.

What the Meta in-app browser actually is

When someone taps a link inside the Facebook or Instagram app, including an ad, Meta doesn’t open it in Safari or Chrome. It opens inside the app’s own embedded browser. On iOS that’s a WKWebView; on Android it’s a Chromium-based custom browser. Meta calls them “Internet Browser” in the UI.

This in-app browser has its own cookie jar, completely sandboxed from Safari, Chrome, or any other system browser. Cookies set in the in-app browser cannot be read by Safari. Cookies set in Safari cannot be read by the in-app browser. They behave as if they belong to two different devices.

Why Meta does this: keeping the user inside the app preserves their session metrics, increases the chance of returning to the feed, and produces more first-party signal that Meta can use after Apple’s App Tracking Transparency made the IDFA-based measurement layer mostly useless. Meta’s incentive is to keep you in-app for as long as possible, including the part where you’d otherwise hand off to your bank.

Where the chain breaks

A standard mobile Meta-ad-to-purchase path on iOS looks like this:

  1. User scrolls Instagram. Taps your ad.
  2. Instagram opens the landing page in the in-app browser. GA4 fires, the _ga and _ga_<container> cookies get set in the in-app cookie jar. The fbclid parameter is on the URL.
  3. User browses, adds to cart, hits checkout. Cookies still live in the in-app browser. GA4 still tracks the same session.
  4. Checkout redirects to the payment provider (Mollie, Adyen, Stripe, Klarna, PayPal, an iDEAL acquirer).
  5. The payment provider runs 3DS, opens the user’s banking app for iDEAL or Apple Pay, or just doesn’t support the in-app browser’s WebView quirks for biometric prompts.
  6. The payment-provider redirect, or the bank-app return URL, gets opened in the system browser (Safari on iOS, Chrome on Android), not back into the in-app browser. This is the OS deciding where a universal link or intent lands, and most banking apps + payment providers force this.
  7. User lands on your thank-you page in Safari. GA4 fires. But the _ga cookie from step 2 lives in the in-app browser, not here. GA4 sees a brand new visitor with a brand new client_id and a brand new session.
  8. The referrer for that thank-you page is the payment provider’s domain. GA4 attributes the purchase event to (direct) / (none) (if the referrer was stripped) or mollie.com / referral (if it wasn’t).

The original Meta click is invisible to GA4 by the time the purchase fires. Meta still counts the conversion (its Pixel + CAPI pipeline relies on the fbclid and the deduplicated server-side event, not on cookies in the system browser), which is why Ads Manager looks healthy while GA4 doesn’t.

⚠️ This isn’t theoretical. On the average Dutch ecommerce store with iDEAL as the dominant payment method, this single mechanism accounts for the majority of the (direct)/(none) purchase share above the noise floor.

Why the payment provider redirect is the trigger

Plenty of users browse from Meta’s in-app browser without breaking anything. Reading a blog post, signing up for a newsletter, even adding to cart, all of that stays inside the in-app cookie jar. Attribution survives.

The break happens at the payment step because:

iDEAL on mobile launches the user’s banking app. When the bank finishes, it returns through a universal link registered to the merchant or PSP, and the OS opens that link in the default browser. The in-app browser is never re-entered.

3DS challenges open in the system browser on some PSP integrations, especially when the in-app browser doesn’t pass the device-fingerprint checks the issuer wants.

Apple Pay and Google Pay sheets can complete inside the in-app browser, but the PSP’s success redirect sometimes still pops out to Safari.

PayPal’s app-switch flow specifically forces the return URL into the system browser on iOS.

Different PSPs handle this differently. Mollie + iDEAL is the most consistent offender on Dutch stores. Adyen-with-iDEAL, Klarna with its mobile app, and Stripe with 3DS-on-mobile all produce the same broken handoff.

How to confirm this is what’s happening to you

Four checks, in order, each one taking a few minutes:

1. Look at the share of Direct purchases. GA4 → Reports → Acquisition → Traffic acquisition → set the secondary dimension to Session default channel group and filter the event to purchase. If Direct is above 30% of purchase events on an ecommerce site, something systemic is breaking attribution. The in-app browser handoff is the most common single cause.

2. Look at the referrer of those Direct purchases. Switch the primary dimension to Session source / medium and look for entries like mollie.com / referral, adyen.com / referral, pay.klarna.com / referral, checkout.stripe.com / referral, paypal.com / referral, or banking-app domains. Every one of those is a session that arrived on your thank-you page from a payment redirect, with no idea where the user originally came from.

3. Check the user agent. In GA4’s Explorer, build a free-form report with Browser, Operating system, and the session count. Meta’s iOS in-app browser shows up with FBAN/FBIOS or Instagram in the user-agent string and gets reported by GA4 as Facebook or Instagram under Browser. Look at the funnel: how many add_to_cart events come from these Browser values vs how many purchase events. If purchase from Facebook/Instagram Browser is a tiny fraction of add_to_cart from the same Browser, you’re watching the handoff break in your own data.

4. Reconcile with Meta Ads Manager. Pull the same date range from Ads Manager (Pixel + CAPI deduplicated Purchase events) and compare to facebook / cpc + instagram / cpc in GA4. A gap of 50%+ is normal when the in-app problem is active. Under 20% means the handoff isn’t your main attribution loss.

The fixes: what works, what doesn’t

Most of the “fixes” you’ll find on this topic only solve a piece of the problem. Here’s an honest read.

What helps a lot

Add payment-provider domains to GA4 Unwanted Referrals. Partial fix. This fixes the case where the user comes back to the same browser (e.g. a desktop checkout that redirects through Mollie and lands back in the same Chrome). It does not fix the in-app → system-browser case, because the cookies are gone regardless of what referrer GA4 sees. Worth doing anyway because it cleans up the desktop variant of the same problem. See GA4 vs Google Ads conversions for the configuration.

Send a server-side purchase event via Meta CAPI with the original fbclid. This is the single biggest win and it’s what makes Meta Ads Manager show the right number. Capture fbclid on the landing page, store it on the cart/order, and send it server-side with the purchase event using Meta’s Conversions API. Meta then matches the conversion to the click regardless of cookies. This fixes attribution in Meta, not in GA4. Meta’s own bidding (Advantage+, CBO) starts performing visibly better within a week, which is usually the actual goal.

Implement a custom channel group for payment redirects. Create a “Payment redirect” channel that captures mollie.com, adyen.com, pay.klarna.com, checkout.stripe.com, paypal.com, ideal*, *.bunq.*, *.ing.*, *.rabobank.*, *.abnamro.* as Source-Match regex. Two benefits: your (direct)/(none) share drops to a more honest number, and you can see how many purchases are clearly getting lost to the handoff. Doesn’t fix attribution, but lets you size the leak. See GA4 custom channel groups for the setup pattern.

What partially helps

⚠️ Pass the original UTMs/click_id through the payment redirect URL. Some PSPs let you append arbitrary query parameters to the redirect_url that come back on the return. If you carry utm_source=facebook&utm_medium=cpc&fbclid=... through to the thank-you page, GA4 can be configured to read those and attribute the new session correctly. The catch: GA4’s auto-detection of UTMs requires they’re set as URL params on a real navigation, and many PSPs strip query params on return. Test the round-trip with a real order before relying on this. When it works, it’s the cleanest GA4-side fix.

⚠️ GA4 user_id stitching. If the user logs in (most ecommerce flows don’t, before checkout), GA4 can stitch the in-app session and the system-browser session into one user. This doesn’t change the session-level acquisition source (the new session still attributes to direct), but reports that aggregate at the user level start showing the right journey. Useful for retention and LTV analysis, not for campaign ROAS.

⚠️ Server-side GA4 via Measurement Protocol with the original client_id. Possible in theory: capture the client_id on the landing page, store it server-side, and fire the purchase event from your backend with that client_id and the original session source. Hard in practice: Measurement Protocol has strict rules (engagement_time_msec required, session_id must be valid, the event must fit GA4’s quality model), and a single typo silently drops the event. If you’re already on server-side GTM, this is worth the engineering. If you’re not, the ROI usually doesn’t justify the build.

What doesn’t help

Adding fbclid as a custom session-source parameter without server-side reinforcement. GA4 doesn’t natively read fbclid the way it reads gclid. You’d have to write a custom GTM tag that reads fbclid and sets traffic_source parameters on the session_start event, and it’d only work if fbclid survived the payment redirect, which it usually doesn’t.

First-party cookies on your own subdomain. Cookies are scoped per-app on iOS regardless of domain. Your _ga cookie on shop.example.com lives in the Instagram in-app browser’s cookie jar and is invisible to Safari, even though both apps loaded the same domain. A first-party setup is good practice for other reasons; it does not solve the cross-app handoff.

Asking users to “open in Safari” before they buy. Realistic conversion impact: negative. Skip.

A pragmatic baseline for a Dutch ecommerce store

If you don’t want to read more about this and just want a checklist:

  1. Server-side Meta CAPI with fbclid captured at landing and sent at purchase. This is the load-bearing fix for Meta-side measurement.
  2. GA4 Unwanted Referrals list including your PSP domains. Cheap and obvious.
  3. Custom channel group with a “Payment redirect” bucket so you stop pretending those sessions are Direct.
  4. Optional: pass fbclid and utm_source=facebook&utm_medium=cpc through the PSP redirect_url and test the round-trip on a real iPhone with the Instagram app installed. If your PSP preserves the params, you also get the GA4-side attribution back.
  5. Accept that GA4 will under-report Meta paid traffic by some amount on mobile, document the gap once you’ve reduced it, and use Ads Manager (with CAPI dedup) as the source of truth for Meta-channel ROAS.

The takeaway

The in-app browser problem isn’t a tagging mistake on your site. It’s a structural mismatch: Meta wants users in-app, payment providers want users in the system browser for security, and the cookies in between can’t follow.

You can’t make Meta stop opening links in its in-app browser, and you can’t make iDEAL stop launching the banking app. What you can do is fix Meta’s measurement via CAPI, stop pretending the lost sessions are Direct, and (if your PSP plays nicely) pass the original campaign through the redirect chain so GA4 has a chance to credit it.

If you’d like an automated check that flags an unusually high Direct share, payment-provider referral leakage, and a few dozen other GA4 issues, you can run our free GA4 audit.

Profielfoto Freek Kampen

By Freek Kampen

Data & Analytics consultant and co-owner of New North Digital. With a background in online advertising, I solve tracking and data issues for entrepreneurs and agencies.

Looking for growth? ▸ Set your New North ▸