WC Analytics Guard
Single-file WordPress plugin that fixes the WooCommerce → GA4 / Google Ads / Meta tracking bugs that quietly cost money: inflated purchase value, double-counted purchase events, lost gclid/fbclid/UTM attribution.
by Abdullah Al Akhzar · github.com/abdullahisactive/wc-analytics-guard · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/abdullahisactive/wc-analytics-guard/archive/refs/heads/main.zipReadme
WC Analytics Guard
A single-file WordPress plugin that fixes the three WooCommerce tracking bugs that quietly cost stores money on Google Ads and Meta:
-
Inflated purchase value. WooCommerce's built-in and many third-party integrations report the order total — shipping + tax + fees included — as the GA4 / Google Ads conversion
value. Smart Bidding then optimises to a number that isn't your revenue. This plugin reports item revenue after discounts, and nothing else. -
Double-counted
purchaseevents. The thank-you page firespurchaseevery time it loads. Customers refresh it, bookmark it, come back to it from email. Each visit is another conversion. This plugin firespurchaseexactly once per order and emits a harmlesspurchase_view_repeaton every visit after. -
Lost attribution.
gclid,gbraid,wbraid,fbclid,msclkid,ttclidand theutm_*parameters are on the landing URL and gone by checkout. This plugin captures them on first touch, stores them on the order, and pushes them to the dataLayer with the purchase — including a Meta-formatfbc/fbpfor the Conversions API.
No settings page. No dependencies. One file.
Install
As a must-use plugin (recommended — can't be deactivated by accident):
cp wc-analytics-guard.php wp-content/mu-plugins/
As a normal plugin: drop wc-analytics-guard.php into
wp-content/plugins/wc-analytics-guard/ and activate it.
Requires WooCommerce 6.0+, PHP 7.4+. Works with the classic and the block (Store API) checkout.
What it pushes
On the thank-you page, once per order:
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: "purchase",
ecommerce: {
transaction_id: "1234",
value: 149.00, // item revenue after discounts — NOT total
currency: "USD",
tax: 12.30,
shipping: 9.99,
coupon: "SPRING10",
items: [
{ item_id: "SKU-1", item_name: "…", item_brand: "…",
item_category: "…", price: 149.00, quantity: 1 }
]
},
attribution: {
gclid: "…", fbclid: "…", utm_source: "google", utm_medium: "cpc",
fbc: "fb.1.1700000000000.…", fbp: "fb.1.…",
landing_page: "https://…", referrer: "https://…"
}
});
Point your existing GA4 / Google Ads / Meta tags in GTM at this purchase
event and the attribution object. The plugin only populates the
dataLayer — it doesn't load GA4, gtag, the Pixel or GTM itself.
Order data
Every order also gets:
_wcag_attribution— the full attribution array (visible under Custom Fields / queryable)._wcag_gclid,_wcag_fbclid,_wcag_utm_source, … — flat copies for exports and server-side CAPI jobs._wcag_purchase_tracked— the timestamp thepurchaseevent first fired.
Configuration (optional)
Constants — define in wp-config.php before the plugin loads:
| Constant | Default | Purpose |
|---|---|---|
WCAG_TRACKED_PARAMS |
gclid,gbraid,wbraid,fbclid,msclkid,ttclid,twclid,li_fat_id,utm_* |
Query params to capture |
WCAG_COOKIE_DAYS |
90 |
First-touch attribution window |
WCAG_DATALAYER |
dataLayer |
dataLayer variable name |
Filters:
| Filter | Use |
|---|---|
wc_analytics_guard_purchase_value |
($value, $order) — override the reported value |
wc_analytics_guard_purchase_payload |
($payload, $order) — change the whole push |
wc_analytics_guard_suppress_repeat |
($bool, $order) — return false to fire on every view |
wc_analytics_guard_brand_meta_keys |
product meta / attribute keys to read item_brand from |
wc_analytics_guard_capture |
($array) — edit the attribution payload before it's stored |
wc_analytics_guard_decimals |
rounding precision for money values |
Notes
- First-touch, not last-touch: once the cookie is set it isn't overwritten, so the campaign that acquired the visitor is the one credited.
- The attribution cookie is not
HttpOnlyon purpose, so GTM can read it client-side if you'd rather wire attribution that way. It contains only click IDs and UTM values. - The
purchaseguard is stored on the order, so it survives caching plugins and works for guests.
License
MIT © Abdullah Al Akhzar