WooCommerce GA4 tracking works either through an extension such as Google Analytics for WooCommerce, which sends events with gtag, or through Google Tag Manager fed by a dataLayer that the store pushes on each ecommerce step. Most errors come from running two of these at once, from a thank-you page that sends the purchase on every load, and from the block-based checkout not firing the hooks an older plugin relies on. Choose one source per event, push the purchase once per order with value and currency, and wire consent through the WP Consent API or GTM.
WooCommerce GA4 tracking is easy to start and easy to get wrong. A store can be tracked by a WooCommerce extension, a Google Tag Manager plugin, a theme snippet and Google for WooCommerce all at once, and each of them sends its own purchase. This page explains the options, the mistakes that inflate or lose revenue, and how to set up WooCommerce Google Tag Manager and GA4 so that every order is counted once.
How WooCommerce GA4 tracking works
WooCommerce itself does not send anything to GA4. Tracking comes from one of three routes:
- Google Analytics for WooCommerce. The free extension from WooCommerce. You add your
G-measurement ID under WooCommerce > Settings > Integration > Google Analytics, and it sends events such as purchases and add to cart with gtag. - Google for WooCommerce. The extension that syncs products to Merchant Center and runs Google Ads campaigns. It adds its own Google tag and sets up conversion actions for purchases, page views, product pages, add to cart and the cart page.
- Google Tag Manager with a dataLayer. A GTM plugin or custom code pushes ecommerce events to the dataLayer, and GTM sends them to GA4, Google Ads, Meta and others.
The first two are quick. GTM is the route when you want control over parameters, more than one destination and a single place to manage consent. Mixing them is where trouble starts.
The block checkout changed the hooks
Since WooCommerce 8.3, new stores get the block-based Cart, Checkout and Order Confirmation by default. WooCommerce's own FAQ says that some actions and filters from the shortcode checkout still work but not all of them, and that extensions must declare compatibility with the blocks. A tracking plugin built for the classic checkout can therefore stop sending begin_checkout, add_shipping_info or add_payment_info after a switch to blocks, while the purchase still arrives. The funnel report then shows a drop that never happened.
The common mistakes
| Mistake | What you see | Cause |
|---|---|---|
| Double purchases | GA4 purchases above WooCommerce orders | The GA extension and a GTM purchase tag both active, or a theme snippet left over |
| Purchase on every load | Same transaction ID days apart | The order received page pushes the purchase without a guard; customers reopen it from the email |
| Missing checkout steps | Checkout funnel breaks after an update | Plugin hooks not supported by the Cart and Checkout blocks |
| Unpaid orders counted | Revenue for bank transfers that never arrived | Purchase sent on the order received page regardless of order status |
| No value or currency | Purchases without revenue | value sent without currency, or prices sent as strings |
| Consent never granted | GA4 traffic drops in the EEA | Banner plugin does not update consent through the WP Consent API |
Google's ecommerce reference requires currency whenever value is set, and GA4 only deduplicates repeat purchases from the same user with the same transaction ID. The fix is at the source, not in GA4. To find doubles by transaction ID, see how to find duplicate purchase events.
Consent on WooCommerce
Google Analytics for WooCommerce sets consent mode to denied by default and integrates with the WP Consent API. It does not provide a banner, so you need a consent plugin that updates the consent state through that API. If you use GTM instead, configure Consent Mode in the container and make sure the banner's update reaches GTM before the first event tag fires.
How to set up WooCommerce Google Tag Manager and GA4
- List every source. Check the GA extension, Google for WooCommerce, any GTM or pixel plugins, and the theme's
header.phpor a code snippets plugin. Note which ones send GA4 or Google Ads events. - Choose one source per destination. If GTM will send GA4 events, switch off the GA extension's tracking. If Google for WooCommerce counts purchases for Google Ads, do not add a second primary purchase conversion in GTM.
- Get a clean dataLayer. Use a GTM plugin that supports the block checkout, or have a developer push GA4-shaped events following a dataLayer specification.
- Push the purchase once. Send it on the order received page only for paid orders, and mark the order so a reload sends nothing.
- Build GTM tags. One GA4 event tag per ecommerce event with a Custom Event trigger, and dataLayer variables for the
ecommercefields. - Test both payment paths. Place a card order and an order with an offsite payment such as PayPal, then reload the confirmation page in Tag Assistant.
WooCommerce documents the woocommerce_thankyou action, which runs on the order received page with the order ID. A developer can use it to push the purchase once per order:
add_action( 'woocommerce_thankyou', function ( $order_id ) {
$order = wc_get_order( $order_id );
if ( ! $order || ! $order->is_paid() || $order->get_meta( '_ga4_purchase_sent' ) ) {
return;
}
$items = array();
foreach ( $order->get_items() as $item ) {
$product = $item->get_product();
$items[] = array(
'item_id' => $product ? $product->get_sku() : (string) $item->get_product_id(),
'item_name' => $item->get_name(),
'price' => (float) $order->get_item_total( $item ),
'quantity' => $item->get_quantity(),
);
}
$data = array(
'event' => 'purchase',
'ecommerce' => array(
'transaction_id' => (string) $order->get_order_number(),
'value' => (float) $order->get_total(),
'tax' => (float) $order->get_total_tax(),
'shipping' => (float) $order->get_shipping_total(),
'currency' => $order->get_currency(),
'items' => $items,
),
);
echo '<script>window.dataLayer=window.dataLayer||[];dataLayer.push({ecommerce:null});dataLayer.push(' . wp_json_encode( $data ) . ');</script>';
$order->update_meta_data( '_ga4_purchase_sent', 'yes' );
$order->save();
} );Check that the hook runs on your confirmation template after a switch to the block-based Order Confirmation, and keep the order number identical across GA4, Google Ads and Meta so each platform can deduplicate.
WooCommerce conversion tracking for Google Ads
For WooCommerce conversion tracking in Google Ads, decide which conversion action is primary for purchases. Google for WooCommerce creates its own purchase conversion with its built-in Google tag; if you also import the GA4 purchase or run a Google Ads tag in GTM, set the extra ones to secondary. Pass the order number as the transaction ID, and add enhanced conversions on the same event if you use them. Only primary actions feed bidding, so a double primary purchase inflates what Smart Bidding sees.
What Tracking Whisper does on a WooCommerce store
Tracking Whisper does not connect to WordPress or WooCommerce and does not install plugins or edit the theme. It works through GTM, GA4 and the live site:
- Audit. A fixed set of checks on the GTM container, including duplicate GA4 configurations, purchase tags without currency or transaction ID, and triggers that can fire twice. See the GTM audit.
- Build. GA4 and Google Ads tags, triggers and variables in its own GTM workspace, published only after a person approves.
- Developer guide. Where the store has to change, such as the purchase push above, it writes the dataLayer guide for your developer.
- Browser checks. It loads key pages in a real browser and checks the dataLayer, the hits and the consent state.
- Monitoring. It watches container versions, key pages and GA4 numbers, and alerts when purchases stop or jump. See monitoring.
Next step
Connect your GTM container and GA4 property and run an audit of your WooCommerce setup; the free plan covers one client with read-only Tag Manager access. Then use tracking setup to build the fixes in a workspace you approve.
Frequently asked questions
Do I need a plugin for WooCommerce GA4 tracking?
No, but you need something that produces the ecommerce data. The free Google Analytics for WooCommerce extension sends purchase and add to cart events with gtag. With Google Tag Manager, a plugin or custom code has to push a dataLayer that GTM reads. What matters is that only one of them sends each GA4 event.
Why are my WooCommerce purchases counted twice in GA4?
Usually two installations send the same order, for example the Google Analytics for WooCommerce extension and a GTM purchase tag, or the order received page sends the purchase every time it loads. Compare GA4 transaction IDs with WooCommerce order numbers and reload the order received page in Tag Assistant to find which.
Does WooCommerce GA4 tracking work with the Cart and Checkout blocks?
It depends on the plugin. Since WooCommerce 8.3 new stores get the block-based Cart, Checkout and Order Confirmation by default, and only some of the classic checkout hooks still work. Check that your tracking plugin declares compatibility with the blocks, and test begin_checkout and purchase after switching.
How does consent work with Google Analytics for WooCommerce?
The extension sets Google's consent mode to denied by default and integrates with the WP Consent API, but it does not include a cookie banner. You need a banner plugin that updates consent through the WP Consent API, otherwise GA4 keeps the denied state.
What is the best WooCommerce conversion tracking setup for Google Ads?
Count each purchase once as a primary conversion: either the Google Ads tag with the order number as transaction ID, or the imported GA4 purchase, not both. Google for WooCommerce adds its own Google tag and conversion actions, so check it is not counting the same purchase as your GTM tag.
Sources
Last updated by Dimitris.