On this page
GA4 ecommerce tracking with GTM works when your store pushes each shopping step into the dataLayer in GA4’s format, and Google Tag Manager sends those events to GA4 with one tag per event. On WooCommerce, that means choosing how the dataLayer gets built, mapping the events, and making sure each order sends one purchase with its order number as transaction_id.
What You Need Before You Start
- GTM installed on every page of the store (see our Google Tag Manager setup guide).
- A Google tag for GA4 in the container with your G-XXXXXXX ID.
- Admin access to WordPress and WooCommerce, plus a staging site if you plan custom code.
- Your checkout type: the classic checkout or the block-based Cart and Checkout.
- A list of every analytics plugin and script already sending to GA4.
- A way to place test orders, such as a 100% coupon or a test payment gateway.
Should You Use Google Analytics for WooCommerce, a dataLayer Plugin or a Custom dataLayer?
Use WooCommerce’s free extension if you want standard reports without GTM. Use a dataLayer plugin or custom code when GTM should run GA4, Google Ads and other pixels from the same ecommerce data.
WooCommerce’s documentation says its free Google Analytics extension tracks product views, list impressions and clicks, add and remove from cart, checkout started and purchases. It also notes purchase tracking needs a payment gateway that returns customers to the order-received page.
| Method | Best for | Trade-off |
| Google Analytics for WooCommerce (free) | GA4 only, minimal upkeep | Less control; not a GTM dataLayer |
| dataLayer plugin + GTM | GA4, Google Ads, Meta from one source | Depends on the plugin keeping up with Woo updates |
| Custom dataLayer + GTM | Custom checkouts, subscriptions, B2B | Needs a developer and testing |
Whichever you choose, run only one. A WooCommerce extension sending GA4 events plus GTM tags sending the same events to the same property doubles everything.
Examples by store type:
- A home goods store with a few hundred products and Google Shopping ads: a dataLayer plugin plus GTM usually covers it.
- A coffee subscription brand: a custom or extended dataLayer, because renewals need separate handling.
- A B2B parts supplier with quote requests and wholesale prices: custom code, so the right price and customer type are sent.
If you also sell on Shopify, the event names are the same but the setup isn’t; see our Shopify GA4 and GTM setup guide.
Which GA4 Ecommerce Events Should a WooCommerce Store Track?
Track the shopping steps Google lists for ecommerce, matched to what happens in WooCommerce. Start with the six core events, then add the rest once those are clean.
| WooCommerce action | GA4 event |
| Shop or category page shown | view_item_list |
| Product clicked in a list | select_item |
| Product page viewed | view_item |
| Added to cart | add_to_cart |
| Cart page viewed | view_cart |
| Removed from cart | remove_from_cart |
| Checkout page loaded | begin_checkout |
| Shipping method chosen | add_shipping_info |
| Payment method chosen | add_payment_info |
| Order received page | purchase |
| Order refunded | refund |
Google’s ecommerce guide says each item needs an item_id or item_name, and recommends both. It also recommends setting currency whenever you send value, because standard reports depend on it.
How Do You Set Up GA4 Ecommerce Tracking in GTM Step by Step?
Get the dataLayer right first, then build one trigger and one tag per event, then test with real orders.
Step 1: Get the dataLayer in GA4 Format
Install your chosen dataLayer plugin, or add custom code, and open a product page with GTM Preview running. You should see events such as view_item with an ecommerce object holding currency, value and items.
dataLayer.push({ ecommerce: null });
dataLayer.push({
event: 'add_to_cart',
ecommerce: {
currency: 'USD',
value: 24.00,
items: [{ item_id: 'SKU-123', item_name: 'Example Mug', price: 24.00, quantity: 1 }]
}
});The first line clears the previous ecommerce object. Google’s Tag Manager guide recommends this so several ecommerce events on one page don’t mix their data.
Step 2: Create Custom Event Triggers
Create one Custom Event trigger per event, named in plain Title Case and matching the event name exactly: “View Item” for view_item, “Add To Cart” for add_to_cart, “Purchase” for purchase.
Step 3: Create One GA4 Event Tag per Event
Create a GA4 Event tag for each event, named Platform – Event – Tag, such as “GA4 – Add To Cart – Tag”. Set the event name, then under More Settings > Ecommerce tick Send ecommerce data with Data Layer as the source.
Tag: GA4 - Purchase - Tag
Type: Google Analytics: GA4 Event
Event name: purchase
More Settings > Ecommerce: Send ecommerce data = on, Data source = Data Layer
Trigger: Purchase (Custom Event, event name = purchase)Separate tags per event take a few more minutes to build, but when add_to_cart breaks after a theme update you fix one tag without touching purchase.
Step 4: Test Each Step and Publish
Run Preview, then go through a full order: product, cart, checkout, payment, order received. Tag Assistant shows which tag fired on which event and why others didn’t. Confirm the values in GA4 DebugView, then publish.
How Do You Stop Duplicate Purchase Events in GA4?
Fire the purchase once per order, no matter how many times the order-received page loads, and always send the order number as transaction_id. Google’s ecommerce guide lists transaction_id as required for purchases.
Duplicates usually come from customers reloading or bookmarking the thank-you page, from two plugins sending the same event, or from a GTM tag and a WooCommerce extension both sending purchase. A simple fix in custom code is to store a flag on the order after the purchase is pushed:
add_action('woocommerce_thankyou', function ($order_id) {
$order = wc_get_order($order_id);
if (!$order || $order->get_meta('_ga4_purchase_sent')) return;
// ...build and echo the purchase dataLayer push here...
$order->update_meta_data('_ga4_purchase_sent', 'yes');
$order->save();
});Many dataLayer plugins include a similar once-per-order option; check its settings before writing code.
How Do You Stop GA4 Crediting Sales to PayPal or Stripe?
Add the payment gateway’s domain to GA4’s unwanted referrals list. Google’s help page uses a third-party payment processor as the main example.
- In GA4, go to Admin > Data streams and open your web stream.
- Open Configure tag settings, show all settings, and choose List unwanted referrals.
- Add each gateway domain your customers pass through, such as paypal.com.
- Save, then place a test order through that gateway and check the session source.
Google allows up to 50 entries per data stream. It also notes that sessions already credited to a gateway stay that way, so expect cleaner data from the change onward, not a fix to history.
How Do You Track Subscription Renewals, Refunds and Orders Without a Thank-You Visit?
Track them from the server, not the browser. A subscription renewal or a refund issued in the admin never loads a page in the customer’s browser, so GTM has nothing to fire on.
- Renewals: send a purchase from the server when the renewal order is paid, with its own transaction_id.
- Refunds: send GA4’s refund event with the original transaction_id; Google lists transaction_id as required for refunds too.
- Off-site gateways that don’t return customers: the free WooCommerce extension won’t see the purchase, so use server-side tracking.
Our server-side tagging setup guide covers the infrastructure, and if Google Ads bids on purchases, the Google Ads conversion tracking guide covers that side.
Troubleshooting WooCommerce GA4 Ecommerce Tracking
| Problem | Likely cause | Fix |
| Revenue in GA4 well below WooCommerce | Consent, ad blockers, gateways that don’t return | Compare order counts; add server-side for gaps |
| Purchase counted twice | Page reloads or two sources | Once-per-order flag; one source |
| Items blank in reports | Send ecommerce data off, or items missing item_id/item_name | Tick Send ecommerce data; fix the items array |
| Wrong currency or value | Value sent as text or currency missing | Send numbers; always send currency |
| Sales credited to paypal.com | Gateway not in unwanted referrals | Add the domain |
| Events stop after a Woo update | Plugin not compatible with new checkout | Check plugin support; retest |
| Tags fire in Preview, GA4 shows nothing | Wrong G- ID or consent denied | Check the Google tag and consent state |
WooCommerce’s own doc notes store and Google data may not match, and consent rules affect what GA4 receives; our Consent Mode v2 guide explains that part.
For the bigger picture across platforms, see ecommerce conversion tracking for GA4, Shopify and WooCommerce.
When Should You Get Help With GA4 Ecommerce Tracking?
Get help when GA4 revenue and WooCommerce orders keep drifting apart, when Google Ads or Meta optimize on purchases you don’t trust, or when subscriptions and refunds never reach GA4. Our Tracking & Analytics service rebuilds WooCommerce ecommerce tracking month-to-month with no lock-in, starting with a free audit.
FAQ
Frequently asked questions
Why Is GA4 Purchase Revenue Lower Than My WooCommerce Orders?
WooCommerce records every order on the server, while GA4 depends on the customer's browser. Declined consent, ad blockers, gateways that don't send customers back to the order-received page, and closed tabs all cause missed purchases. Compare order counts rather than revenue first, then close the biggest gap, often with server-side tracking.
Does a dataLayer Plugin Work With WooCommerce's Block Checkout?
It depends on the plugin and version. Block-based Cart and Checkout work differently from the classic shortcode checkout, so some events can stop firing after you switch. Check the plugin's documentation for block checkout support and run a full test order in GTM Preview after every switch or update.
Why Are item_category or Price Missing From My view_item_list Events?
The dataLayer isn't including them in the items array. Open the event in GTM Preview, look at the ecommerce object, and check each item has item_id or item_name, price and the category fields you expect. If they are missing there, the fix is in the plugin settings or dataLayer code, not in GTM.
Why Isn't My Transaction ID or Currency Showing Correctly in GA4?
Usually the dataLayer sends the wrong field, such as the internal order ID instead of the order number customers see, or leaves currency out. Send the order number as transaction_id, send value as a number, and always include currency so GA4's reports can use the value.
Do I Need GA4 Measurement Protocol, or Is Browser Tracking Enough?
Browser tracking through GTM is enough for most stores as a start. Server-to-server sending becomes worth it when a meaningful share of orders never reaches GA4, or when you need renewals and refunds that happen without a customer visit.
Should I Send WooCommerce Customer IDs to GA4 as User-ID?
You can send a non-personal internal customer ID, but never an email address or name. Only send it when the visitor's consent allows analytics storage, and check your privacy policy covers it before switching it on.
5 sources & references
- Google for Developers Measure ecommerce (Google Analytics) developers.google.com
- Google for Developers Measure ecommerce (Tag Manager) developers.google.com
- WooCommerce Google Analytics for WooCommerce woocommerce.com
- Analytics Help Identify unwanted referrals support.google.com
- Tag Manager Help Preview and debug containers support.google.com
Official pages we checked when writing this article.







