WooCommerce Tracking Implementation
Self-Hosted Means Full Access, But Also Full Responsibility
Unlike Shopify's locked-down checkout, WooCommerce runs on your own WordPress install with full PHP-level access to every order lifecycle hook. This makes genuinely reliable server-side tracking far easier to implement — you can hook directly into WooCommerce's own action system rather than reverse-engineering webhook payloads — but it also means there's no platform-enforced structure; tracking quality depends entirely on implementation discipline.
The Core Hooks for Ecommerce Events
WooCommerce fires well-documented PHP action hooks at every meaningful lifecycle point: woocommerce_add_to_cart, woocommerce_checkout_order_processed (order created, payment pending), woocommerce_order_status_completed (payment confirmed — the right moment for a purchase event), and woocommerce_order_refunded. Hooking into woocommerce_order_status_completed rather than woocommerce_checkout_order_processed for purchase tracking avoids counting orders that fail payment or get cancelled before completion.
// Conceptually what a WooCommerce purchase hook looks like (PHP, shown
// here as commented pseudocode for clarity in this TS-formatted codebase)
/*
add_action('woocommerce_order_status_completed', function($order_id) {
$order = wc_get_order($order_id);
$items = [];
foreach ($order->get_items() as $item) {
$product = $item->get_product();
$items[] = [
'item_id' => $product->get_sku() ?: (string) $product->get_id(),
'item_name' => $item->get_name(),
'price' => (float) $order->get_item_total($item),
'quantity' => $item->get_quantity(),
];
}
$payload = [
'client_id' => sanitize_text_field($_COOKIE['_ga'] ?? wp_generate_uuid4()),
'events' => [[
'name' => 'purchase',
'params' => [
'transaction_id' => (string) $order->get_id(),
'value' => (float) $order->get_total(),
'currency' => $order->get_currency(),
'items' => $items,
],
]],
];
wp_remote_post(
'https://www.google-analytics.com/mp/collect?measurement_id=XXX&api_secret=YYY',
['body' => json_encode($payload), 'blocking' => false]
);
});
*/Reading the GA Cookie Server-Side for Client ID Continuity
_ga cookie (GA4's client ID cookie) directly from $_COOKIE in your PHP hook, giving you accurate client ID stitching without the cross-system handoff problem Shopify's separate checkout domain creates. This is a significant advantage of WooCommerce's same-domain architecture for measurement accuracy.Plugin Ecosystem Tradeoffs
Plugins like WooCommerce Google Analytics Integration or various GTM-for-WooCommerce plugins handle this wiring out of the box, trading implementation control for setup speed. These are reasonable for simpler stores, but they typically implement client-side-only tracking via dataLayer pushes on the Thank You page — which inherits all the usual client-side reliability problems (ad blockers, page abandonment before the script fires, browser privacy restrictions). For revenue-critical measurement, a custom server-side hook as shown above remains the more reliable path even though it requires development effort.
Handling Partial Refunds and Order Edits
WooCommerce supports partial refunds and post-purchase order edits (adding/removing line items), both of which need their own hook handlers (woocommerce_order_refunded, woocommerce_saved_order_items) sending corresponding refund events or adjusted value events to GA4/ad platforms — these are frequently skipped in initial implementations and only discovered as a gap when finance reconciliation reveals systematic revenue overstatement.
Non-Blocking Requests Can Silently Fail
'blocking' => false pattern shown above (common for not slowing down the checkout page response) means your PHP code never sees the Measurement Protocol response or any error from it. Pair non-blocking tracking calls with a separate logging mechanism (writing to a database table or log file on failure) so broken tracking doesn't go unnoticed for months.What's Next?
WooCommerce's same-domain, full-access architecture is relatively friendly for implementation. Magento, with its more complex enterprise architecture, and headless commerce setups present different and often harder tracking challenges worth exploring next.
I build these systems professionally.
Whether it's a RAG pipeline, analytics migration, or AI workflow — let's talk.