WordPress and WooCommerce

    WooCommerce Server-Side Tracking Plugin

    A practical guide to running WooCommerce ecommerce tracking through a first-party server container, using the free Tracking Hippo plugin for the data layer and the order webhooks.

    12 agosto 2026 · 11 min read

    WooCommerce stores lose conversion data in two places: the browser, where blockers and tracking prevention drop tag requests, and the checkout itself, where a customer can leave the thank-you page before a client-side purchase tag ever fires. A server-side setup addresses both. The browser sends structured ecommerce events to a first-party endpoint, and the store's own backend sends the order a second time, from PHP, where no blocker can reach it. This guide covers how to build that with the Tracking Hippo plugin and a server container.

    What server-side tracking changes for a WooCommerce store

    Server-side tagging splits collection from delivery. The browser's only job becomes describing what happened, in a data layer, and sending it to one endpoint on your own domain. Decisions about which platforms receive the event, what is stripped from it and how it is formatted move into a container you control.

    For a store, the practical gain is that purchase data stops depending on whether a third-party script survived the page. The order exists in the database whether or not the browser cooperated, so it can be delivered from the server as the authoritative record.

    The container is served from your domain, so blocklists built around googletagmanager.com do not match it
    Cookies set over HTTP are not subject to the seven-day cap browsers apply to script-set cookies
    Personal data can be hashed on the server before it is ever exposed to the page
    One validated event can be fanned out to GA4, Meta, Google Ads and TikTok without adding browser scripts

    The ecommerce events a WooCommerce store should emit

    GA4 defines a standard funnel, and the value of using the standard names is that every downstream platform already understands them. The plugin emits the complete set rather than a subset, because a funnel with gaps cannot be used for drop-off analysis and the missing steps are usually the ones that explain a decline.

    Item detail matters as much as the event names. Remarketing audiences and Merchant Center matching depend on the item id agreeing with your product feed, so the id source is configurable rather than assumed.

    view_item_list and select_item on shop, category, tag and search listings
    view_item, add_to_cart, remove_from_cart and view_cart across the catalogue and basket
    begin_checkout, add_shipping_info and add_payment_info through the checkout steps
    purchase on the order-received page, deduplicated so a reload cannot count it twice

    Why the Cart and Checkout blocks need different handling

    Most WooCommerce tracking integrations were written against the classic shortcode templates and hook into template actions such as woocommerce_after_cart. Those hooks do not exist in the block-based cart and checkout, which have been the default for new stores since WooCommerce 8.3. An integration that relies on them silently reports nothing on a modern store, and the gap is easy to miss because the product pages still work.

    Two changes fix it. Page-level events are derived from the cart itself using WooCommerce's conditional tags, so they fire regardless of how the page is rendered. Cart mutations are read from the wc/store/cart data store, because the DOM events the blocks dispatch carry no item payload of their own.

    Use is_cart() and is_checkout() rather than template hooks for view_cart and begin_checkout
    Diff successive cart snapshots to derive add_to_cart and remove_from_cart with real quantities
    Read prices from the Store API in minor units and convert with the currency's minor unit
    Keep the classic listeners as well, since plenty of stores still run the shortcode templates

    Consent, identity and the order webhook

    Consent Mode defaults have to be published before the container loads, exactly once. If your consent banner already sends them, a second set from a plugin creates a race that is hard to debug. Decide which component owns the defaults and switch the other one off.

    Identity is the other half. Enhanced Conversions and Customer Match only match hashed values that were normalised the way Google expects first, and the most common failure is phone numbers. A number typed as +31 (0)6 1234 5678 must be hashed as +31612345678, because the parenthesised trunk zero is dropped in international format. Hashing the string as typed produces a value that never matches anything.

    Publish Consent Mode v2 defaults for all seven signals, in one place only
    Normalise email, phone and name before hashing, and hash them in PHP rather than the browser
    Capture the analytics identifier at checkout, while the cookies are still readable
    Send the order from the server with a deterministic event id so the receiver can deduplicate it

    Verify the funnel on a real order, not in the settings screen

    Configuration screens tell you what is switched on, not what arrived. Place a genuine test order on both the classic and the block checkout, watch each event in the container's preview mode, and confirm the purchase reaches its destination exactly once. Reload the thank-you page and confirm it does not arrive twice.

    WooCommerce server-side tracking: implementation checklist

    Work through this in order. Each step has an output you can verify before moving on, which is what keeps a tracking rebuild from turning into a guessing exercise.

    1. 01

      Provision the container and a first-party subdomain

      Deploy a server container and point a subdomain of the store's own domain at it. A container on an unrelated domain still works, but the cookies it sets are not first-party and the attribution advantage is lost.

    2. 02

      Install the plugin and connect it

      Upload the plugin ZIP, activate it, then enter the container URL and the GTM web container ID. Use the connection test to confirm the container answers before configuring anything else.

    3. 03

      Decide who owns consent

      If your consent banner publishes Consent Mode defaults, leave the plugin's consent tab switched off. If it does not, enable it and set the seven signals, the region scope and the wait-for-update window.

    4. 04

      Match item ids to your product feed

      Choose whether item_id is the SKU or the product ID and add a prefix if your feed exports one. Compare a handful of items against Merchant Center before you rely on remarketing audiences.

    5. 05

      Enable the server-side order webhook

      Turn on purchase and refund delivery and point it at the container endpoint. Delivery runs on a background job with retries, so checkout is never slowed down and a transient failure is not a lost conversion.

    6. 06

      Deduplicate before you compare numbers

      The browser purchase and the server purchase describe the same order. Match them on the transaction id in the container so the destination counts one conversion, then reconcile a day of orders against the WooCommerce reports.

    Measure the orders you actually took

    A WooCommerce measurement setup is working when the revenue in your analytics matches the revenue in your store, and you can explain any difference. Server-side delivery of the order is what closes most of that gap, because it stops depending on the browser finishing its work.

    Build it so the pieces are separable: the data layer describes behaviour, the webhook states what was sold, and the container decides where each goes. When a platform changes its requirements, and they do, you change one mapping rather than re-instrumenting the store.

    WooCommerce server-side tracking: common questions

    Do I still need a browser data layer if the order is sent from the server?

    Yes. The server webhook covers purchases and refunds. Everything earlier in the funnel, from product views to checkout steps, only exists in the browser, and GA4 needs those events to attribute the purchase to a session and a source.

    Does this work with the Cart and Checkout blocks?

    It does, provided the integration does not rely on classic template hooks. Page events should come from the cart via WooCommerce's conditional tags, and add or remove events from the wc/store/cart data store, which is where the block front-end keeps its state.

    Will the purchase be counted twice if I send it from the browser and the server?

    Only if you do not deduplicate. Send a stable identifier derived from the order with both copies, usually the transaction id, and match on it in the server container so the destination platform records one conversion.

    Can I run this alongside another Google Tag Manager plugin?

    One plugin should inject the container. Two containers on one page means every event is collected twice and reporting doubles. Keep the data layer from whichever plugin you prefer and disable container output in the other.

    Primary sources and further reading

    Articoli correlati

    Run WooCommerce tracking on managed EU infrastructure

    Deploy a first-party tagging endpoint with predictable pricing, and install the free WordPress plugin that feeds it.