🎁 Free consultation. Book now. 🆕 New service: GEO optimization for AI search engines 📝 New blog post
Case Study

The GA4 WooCommerce plugin showed 40% fewer orders than actually happened because AdBlock, Safari, and Brave were simply blocking the tracker. After implementing server-side Measurement Protocol, 100% of purchase events were recorded with full attribution.

WooCommerce + GA4: how not to lose 40% of orders

Server-side purchase delivery through Measurement Protocol with full attribution: client_id, session_id, gclid

🛒 E-commerce / WooCommerce 🔧 WordPress 📊 GA4 Measurement Protocol
🛒
+40%
Recovered conversions
+40% recovered conversions
100% attribution

This case study is for you if...

🛒 WooCommerce store A WooCommerce store using Google Ads where GA4 purchase counts do not match actual orders
🔧 GA4 via plugin or GTM AdBlock, Safari ITP, and Brave are blocking the GA4 tracker, so you lose purchase data
📊 Data fell into "(not set)" Attribution is broken: source/medium shows "(not set)," gclid is not passed, and ROAS is inaccurate
🔒 Google Ads ROAS is inaccurate Google Ads Smart Bidding is optimizing on incomplete data, so you end up overpaying for clicks

See yourself in this? Keep reading: this case study shows the solution.

About the project

🛒

An e-commerce store running on WordPress + WooCommerce

An e-commerce store running on WordPress + WooCommerce. GA4 was integrated through GTM and plugins, which is the standard setup for most WordPress stores.

🔥

Challenge

Analytics was missing up to 40% of orders because AdBlock, iOS Safari, and Brave were blocking trackers. Events were sent only from the frontend, users could leave before the call fired, data landed in "(not set)," and attribution was broken.

🎯

Goals

01 Recover tracking of every purchase event in GA4
02 Preserve full attribution: source, medium, campaign, and gclid
03 Improve ROAS accuracy in Google Ads

What can go wrong here

And why most contractors get it wrong

Plugins mean frontend only

Standard GA4 plugins for WooCommerce send purchase events with frontend JavaScript. AdBlock, Safari ITP, Brave, and Firefox ETP block that request, so up to 40% of orders are never recorded.

How I solved it: A PHP handler on woocommerce_thankyou with server-side delivery

Attribution is lost between pages

client_id, session_id, and gclid have to survive from the first visit through purchase. If JS fails to read them in time or the user passes through a redirect, attribution breaks. GA4 shows "(not set)" and Google Ads misses the conversion.

How I solved it: JS reads client_id and session_id via gtag("get", ...), stores them in cookies, and passes them to the server

Server-side purchase validation

Server-side Measurement Protocol does not give you DebugView by default. If the payload is invalid, the event is silently dropped. Without logging and validation, you can miss the problem for weeks.

How I solved it: Full logging plus GA4 DebugView and session-link validation

What was done

STEP 01

PHP handler on woocommerce_thankyou

Built a custom PHP handler on the woocommerce_thankyou hook that collects all order data, including transaction_id, items, brand, and value.

STEP 02

JS for client_id and session_id

A JavaScript file reads client_id and session_id from GA4 via gtag("get", ...), stores them in cookies, and passes them to the server along with the order submission.

STEP 03

Server-side delivery to GA4

The server sends the purchase event to google-analytics.com/mp/collect with full payload data including client_id, session_id, source/medium/campaign, and gclid/gbraid.

STEP 04

Logging and validation

Every send is fully logged and checked in GA4 DebugView, validating that the purchase attaches to the correct session and funnel.

What I did differently

1

A PHP handler instead of a JS plugin

I built a custom PHP handler on the woocommerce_thankyou hook. The server sends purchase events directly to google-analytics.com/mp/collect, so no AdBlock can stop the server request.

2

Full attribution through a cookie bridge

JS reads client_id and session_id from GA4 and stores them in a first-party cookie. At checkout, PHP takes those values and sends them to Measurement Protocol together with gclid and gbraid. The result is 100% attribution.

3

Logging and validating every send

Every server-side purchase is logged with transaction_id, client_id, session_id, and the GA4 response. DebugView is then used to verify that the purchase is attached to the right session and funnel.

Numbers that speak for themselves

+40%
Recovered conversions
100%
Attribution preserved
ROAS in Google Ads

Before and after

Purchase events Up to 40% lost
100% Server-side MP
Attribution (not set)
100% client_id + gclid
Sending JS frontend
PHP server-side Measurement Protocol
Validation Did not exist
Full Logging plus DebugView
What this means for the business
+40%
orders that previously were not recorded in GA4
100%
attribution preserved: source, medium, gclid

In simple terms, Google Ads can finally see every purchase and optimize bids correctly. The same budget now produces more conversions.

Free resource

Guide: server-side GA4 for WooCommerce without plugins

How to send purchase events from PHP through Measurement Protocol with full attribution. A step-by-step guide with code examples.

  • PDF, 3 pages: architecture plus code
  • PHP template for woocommerce_thankyou
  • No signup, no spam
Get it via Telegram →
PDF
WooCommerce server-side GA4 guide
3 pages PDF • 420 KB
FREE

FAQ

Why does a GA4 plugin for WooCommerce lose orders?

Standard GA4 plugins send purchase events from frontend JavaScript. AdBlock, Safari ITP, Brave, and Firefox ETP block that request, so up to 40% of orders are never recorded. The fix is server-side delivery through Measurement Protocol.

How do you set up server-side purchase tracking for WooCommerce through Measurement Protocol?

You need a PHP handler on the woocommerce_thankyou hook that collects transaction_id, items, and value, then sends them to google-analytics.com/mp/collect. For attribution, JS stores client_id and session_id in a cookie, and PHP sends them together with gclid.

How do you verify that server-side purchase tracking works correctly?

Use three layers of validation: 1) log every send with the response code, 2) check in GA4 DebugView that the purchase attaches to the correct session, and 3) compare WooCommerce orders against GA4 purchases over a week.

Ready for growth?

Let's discuss your project and find the solution that works for your business.