WooCommerce + GA4 E-commerce Tracking
Comprehensive guide to tracking WooCommerce transactions, product performance, and customer behavior with Google Analytics 4.
Overview
WooCommerce is WordPress's leading e-commerce plugin with 5+ million active installations. Proper GA4 integration enables:
- Product performance analysis (views, add-to-cart rates, revenue)
- Customer journey tracking (browse → cart → checkout → purchase)
- Revenue attribution (traffic sources, campaigns, channels)
- Conversion funnel optimization (checkout abandonment, payment failures)
Implementation Methods
Method 1: MonsterInsights Enhanced E-commerce (Easiest)
Best for: Non-technical users, quick setup, automatic tracking
Setup Steps
Install MonsterInsights Pro
- Purchase MonsterInsights Pro license ($199.50+/year)
- Install and activate plugin
- Connect to Google Analytics account
Enable E-commerce Addon
- Navigate to Insights → Addons
- Activate Enhanced Ecommerce
- Click Settings
Configure E-commerce Settings
Insights → Settings → eCommerce ✓ Enable Enhanced Ecommerce Tracking ✓ Use Measurement Protocol API (for server-side tracking) ✓ Enable Automatic Product Impressions ✓ Enable Add to Cart Tracking ✓ Enable Checkout Step Tracking ✓ Enable Transaction TrackingVerify in GA4
- Go to GA4 → Reports → Monetization → E-commerce purchases
- Make a test purchase
- Confirm transaction appears
What MonsterInsights Tracks Automatically
// Product Impressions (shop pages, archives)
view_item_list
// Product Detail Views
view_item
// Add to Cart
add_to_cart
// Remove from Cart
remove_from_cart
// Begin Checkout
begin_checkout
// Purchase
purchase
MonsterInsights Limitations
- Annual subscription cost
- Limited customization options
- May track duplicate events if custom code exists
- Performance overhead from plugin
Method 2: Official WooCommerce Google Analytics Integration
Best for: Users wanting official WooCommerce extension
Install WooCommerce Google Analytics Integration
- WooCommerce → Extensions
- Search "Google Analytics"
- Purchase/Install WooCommerce Google Analytics ($79/year)
Configuration
WooCommerce → Settings → Integration → Google Analytics Google Analytics Tracking ID: G-XXXXXXXXXX ✓ Enable Enhanced E-commerce Tracking ✓ Track Add to Cart ✓ Track Remove from Cart ✓ Track Product Impressions □ Track logged-in administrators (disable)Advanced Settings
- Event Tracking: Select events to track
- IP Anonymization: Enable for GDPR
- Enhanced Link Attribution: Enable for click tracking
Method 3: Manual Implementation (Full Control)
Best for: Developers, custom requirements, performance optimization
Step 1: Track Product Impressions
// Add to functions.php or custom plugin
add_action('woocommerce_after_shop_loop_item', 'track_product_impression');
function track_product_impression() {
global $product;
?>
<script>
gtag('event', 'view_item_list', {
'items': [{
'item_id': '<?php echo esc_js($product->get_sku() ?: $product->get_id()); ?>',
'item_name': '<?php echo esc_js($product->get_name()); ?>',
'item_category': '<?php echo esc_js(wp_strip_all_tags(wc_get_product_category_list($product->get_id()))); ?>',
'item_brand': '<?php echo esc_js(get_post_meta($product->get_id(), '_brand', true)); ?>',
'price': <?php echo $product->get_price(); ?>,
'currency': '<?php echo get_woocommerce_currency(); ?>'
}]
});
</script>
<?php
}
Step 2: Track Product Views
add_action('woocommerce_after_single_product', 'track_product_view');
function track_product_view() {
global $product;
$categories = wp_get_post_terms($product->get_id(), 'product_cat', array('fields' => 'names'));
?>
<script>
gtag('event', 'view_item', {
'currency': '<?php echo get_woocommerce_currency(); ?>',
'value': <?php echo $product->get_price(); ?>,
'items': [{
'item_id': '<?php echo esc_js($product->get_sku() ?: $product->get_id()); ?>',
'item_name': '<?php echo esc_js($product->get_name()); ?>',
'item_category': '<?php echo esc_js(implode('/', $categories)); ?>',
'item_variant': '<?php echo esc_js($product->is_type('variable') ? 'variable' : 'simple'); ?>',
'price': <?php echo $product->get_price(); ?>,
'quantity': 1
}]
});
</script>
<?php
}
Step 3: Track Add to Cart
add_action('wp_footer', 'track_add_to_cart_js');
function track_add_to_cart_js() {
if (!is_product()) {
return;
}
global $product;
?>
<script>
jQuery(document).ready(function($) {
$('.single_add_to_cart_button').on('click', function() {
// Get variation data if variable product
let variation = {};
if ($('.variations_form').length) {
const variationData = $('.variations_form').data('product_variations');
const selectedVariation = $('.variation_id').val();
variation = variationData.find(v => v.variation_id == selectedVariation) || {};
}
gtag('event', 'add_to_cart', {
'currency': '<?php echo get_woocommerce_currency(); ?>',
'value': parseFloat(variation.display_price || <?php echo $product->get_price(); ?>),
'items': [{
'item_id': variation.sku || '<?php echo esc_js($product->get_sku() ?: $product->get_id()); ?>',
'item_name': '<?php echo esc_js($product->get_name()); ?>',
'price': parseFloat(variation.display_price || <?php echo $product->get_price(); ?>),
'quantity': parseInt($('.qty').val() || 1)
}]
});
});
});
</script>
<?php
}
Step 4: Track Remove from Cart
add_action('wp_footer', 'track_remove_from_cart');
function track_remove_from_cart() {
if (!is_cart()) {
return;
}
?>
<script>
jQuery(document).ready(function($) {
$(document.body).on('click', '.product-remove a.remove', function() {
const $row = $(this).closest('tr');
const itemName = $row.find('.product-name a').text();
const itemPrice = parseFloat($row.find('.product-price .amount').text().replace(/[^0-9.]/g, ''));
const itemQty = parseInt($row.find('.qty').val() || 1);
gtag('event', 'remove_from_cart', {
'currency': '<?php echo get_woocommerce_currency(); ?>',
'value': itemPrice * itemQty,
'items': [{
'item_name': itemName,
'price': itemPrice,
'quantity': itemQty
}]
});
});
});
</script>
<?php
}
Step 5: Track Begin Checkout
add_action('woocommerce_before_checkout_form', 'track_begin_checkout');
function track_begin_checkout() {
$cart = WC()->cart;
$items = array();
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$product = $cart_item['data'];
$items[] = array(
'item_id' => $product->get_sku() ?: $product->get_id(),
'item_name' => $product->get_name(),
'price' => $product->get_price(),
'quantity' => $cart_item['quantity']
);
}
?>
<script>
gtag('event', 'begin_checkout', {
'currency': '<?php echo get_woocommerce_currency(); ?>',
'value': <?php echo $cart->get_total(''); ?>,
'coupon': '<?php echo esc_js(implode(', ', $cart->get_applied_coupons())); ?>',
'items': <?php echo json_encode($items); ?>
});
</script>
<?php
}
Step 6: Track Add Payment Info
add_action('woocommerce_review_order_before_payment', 'track_add_payment_info');
function track_add_payment_info() {
?>
<script>
jQuery(document).ready(function($) {
$('input[name="payment_method"]').on('change', function() {
const paymentMethod = $(this).val();
gtag('event', 'add_payment_info', {
'currency': '<?php echo get_woocommerce_currency(); ?>',
'value': <?php echo WC()->cart->get_total(''); ?>,
'payment_type': paymentMethod
});
});
});
</script>
<?php
}
Step 7: Track Purchase (Most Important)
add_action('woocommerce_thankyou', 'track_purchase_complete');
function track_purchase_complete($order_id) {
if (!$order_id) {
return;
}
// Prevent duplicate tracking on page refresh
$tracked = get_post_meta($order_id, '_ga4_tracked', true);
if ($tracked) {
return;
}
$order = wc_get_order($order_id);
$items = array();
foreach ($order->get_items() as $item_id => $item) {
$product = $item->get_product();
$items[] = array(
'item_id' => $product->get_sku() ?: $product->get_id(),
'item_name' => $item->get_name(),
'item_category' => wp_strip_all_tags(wc_get_product_category_list($product->get_id())),
'price' => $item->get_total() / $item->get_quantity(),
'quantity' => $item->get_quantity()
);
}
?>
<script>
gtag('event', 'purchase', {
'transaction_id': '<?php echo $order->get_order_number(); ?>',
'value': <?php echo $order->get_total(); ?>,
'currency': '<?php echo $order->get_currency(); ?>',
'tax': <?php echo $order->get_total_tax(); ?>,
'shipping': <?php echo $order->get_shipping_total(); ?>,
'coupon': '<?php echo implode(', ', $order->get_coupon_codes()); ?>',
'items': <?php echo json_encode($items); ?>
});
</script>
<?php
// Mark as tracked
update_post_meta($order_id, '_ga4_tracked', 'yes');
}
Server-Side Tracking with Measurement Protocol
Client-side tracking can miss conversions due to ad blockers or checkout redirects. Implement server-side tracking for accuracy.
Setup Server-Side Purchase Tracking
add_action('woocommerce_order_status_completed', 'server_side_ga4_purchase');
function server_side_ga4_purchase($order_id) {
$order = wc_get_order($order_id);
// Prevent duplicate tracking
$tracked_server = get_post_meta($order_id, '_ga4_server_tracked', true);
if ($tracked_server) {
return;
}
// Get GA4 Measurement ID and API Secret (store in wp-config.php)
$measurement_id = defined('GA4_MEASUREMENT_ID') ? GA4_MEASUREMENT_ID : 'G-XXXXXXXXXX';
$api_secret = defined('GA4_API_SECRET') ? GA4_API_SECRET : 'your-api-secret';
// Get or generate client ID
$client_id = isset($_COOKIE['_ga']) ? substr($_COOKIE['_ga'], 6) : wp_generate_uuid4();
// Build items array
$items = array();
foreach ($order->get_items() as $item) {
$product = $item->get_product();
$items[] = array(
'item_id' => $product->get_sku() ?: $product->get_id(),
'item_name' => $item->get_name(),
'price' => $item->get_total() / $item->get_quantity(),
'quantity' => $item->get_quantity()
);
}
// Build payload
$payload = array(
'client_id' => $client_id,
'events' => array(
array(
'name' => 'purchase',
'params' => array(
'transaction_id' => $order->get_order_number(),
'value' => floatval($order->get_total()),
'currency' => $order->get_currency(),
'tax' => floatval($order->get_total_tax()),
'shipping' => floatval($order->get_shipping_total()),
'items' => $items
)
)
)
);
// Send to GA4 Measurement Protocol
$url = "https://www.google-analytics.com/mp/collect?measurement_id={$measurement_id}&api_secret={$api_secret}";
wp_remote_post($url, array(
'body' => json_encode($payload),
'headers' => array('Content-Type' => 'application/json')
));
update_post_meta($order_id, '_ga4_server_tracked', 'yes');
}
Get GA4 API Secret
- Go to GA4 → Admin → Data Streams
- Click your web stream
- Scroll to Measurement Protocol API secrets
- Click Create → Name it → Copy secret
Store Credentials Securely
// Add to wp-config.php (never commit to version control)
define('GA4_MEASUREMENT_ID', 'G-XXXXXXXXXX');
define('GA4_API_SECRET', 'your-api-secret-here');
Refund Tracking
Track refunds to maintain accurate revenue reporting:
add_action('woocommerce_order_status_refunded', 'track_order_refund');
function track_order_refund($order_id) {
$order = wc_get_order($order_id);
$items = array();
foreach ($order->get_items() as $item) {
$product = $item->get_product();
$items[] = array(
'item_id' => $product->get_sku() ?: $product->get_id(),
'item_name' => $item->get_name(),
'price' => $item->get_total() / $item->get_quantity(),
'quantity' => $item->get_quantity()
);
}
// Send server-side refund event
$measurement_id = defined('GA4_MEASUREMENT_ID') ? GA4_MEASUREMENT_ID : 'G-XXXXXXXXXX';
$api_secret = defined('GA4_API_SECRET') ? GA4_API_SECRET : '';
$payload = array(
'client_id' => wp_generate_uuid4(),
'events' => array(
array(
'name' => 'refund',
'params' => array(
'transaction_id' => $order->get_order_number(),
'value' => floatval($order->get_total()),
'currency' => $order->get_currency(),
'items' => $items
)
)
)
);
wp_remote_post("https://www.google-analytics.com/mp/collect?measurement_id={$measurement_id}&api_secret={$api_secret}", array(
'body' => json_encode($payload),
'headers' => array('Content-Type' => 'application/json')
));
}
WooCommerce Subscriptions Tracking
For WooCommerce Subscriptions plugin:
// Track subscription sign-ups
add_action('woocommerce_subscription_status_active', 'track_subscription_signup', 10, 1);
function track_subscription_signup($subscription) {
$subscription_id = $subscription->get_id();
$tracked = get_post_meta($subscription_id, '_ga4_subscription_tracked', true);
if ($tracked) {
return;
}
?>
<script>
gtag('event', 'subscription_signup', {
'event_category': 'Subscriptions',
'event_label': '<?php echo esc_js($subscription->get_name()); ?>',
'value': <?php echo $subscription->get_total(); ?>,
'currency': '<?php echo $subscription->get_currency(); ?>',
'subscription_period': '<?php echo $subscription->get_billing_period(); ?>'
});
</script>
<?php
update_post_meta($subscription_id, '_ga4_subscription_tracked', 'yes');
}
// Track subscription cancellations
add_action('woocommerce_subscription_status_cancelled', 'track_subscription_cancel', 10, 1);
function track_subscription_cancel($subscription) {
gtag('event', 'subscription_cancel', {
'event_category': 'Subscriptions',
'event_label': $subscription->get_name(),
'subscription_id': $subscription->get_id()
});
}
GTM Implementation for WooCommerce
Alternative approach using Google Tag Manager data layer:
add_action('wp_footer', 'woocommerce_gtm_data_layer');
function woocommerce_gtm_data_layer() {
if (is_product()) {
global $product;
?>
<script>
dataLayer.push({
'event': 'productView',
'ecommerce': {
'detail': {
'products': [{
'id': '<?php echo esc_js($product->get_sku() ?: $product->get_id()); ?>',
'name': '<?php echo esc_js($product->get_name()); ?>',
'price': '<?php echo $product->get_price(); ?>',
'category': '<?php echo esc_js(wp_strip_all_tags(wc_get_product_category_list($product->get_id()))); ?>'
}]
}
}
});
</script>
<?php
}
}
See GTM Data Layer Guide for complete WooCommerce GTM setup.
Testing E-commerce Tracking
1. Enable Test Mode in WooCommerce
// Add to wp-config.php for testing environment
define('WC_TAX_ROUNDING_MODE', 'auto');
define('WP_ENVIRONMENT_TYPE', 'staging');
2. Make Test Purchases
- Use Cash on Delivery payment method (no real charges)
- Or use Stripe Test Mode with test cards
- Test card:
4242 4242 4242 4242, Exp: any future date, CVC: any 3 digits
3. Verify in GA4 DebugView
// Enable debug mode
add_action('wp_head', 'enable_ga4_debug');
function enable_ga4_debug() {
if (defined('WP_ENVIRONMENT_TYPE') && WP_ENVIRONMENT_TYPE === 'staging') {
?>
<script>
gtag('config', 'G-XXXXXXXXXX', {
'debug_mode': true
});
</script>
<?php
}
}
4. Check E-commerce Reports
After 24-48 hours, verify data in:
- Reports → Monetization → Overview
- Reports → Monetization → E-commerce purchases
- Explore → E-commerce funnel
Deduplication Best Practices
Prevent double-counting purchases:
// Check if purchase already tracked before firing event
function track_purchase_complete($order_id) {
// Check custom meta
if (get_post_meta($order_id, '_ga4_tracked', true)) {
return; // Already tracked, skip
}
// ... tracking code ...
// Mark as tracked
update_post_meta($order_id, '_ga4_tracked', 'yes');
}
Performance Optimization
Conditional Script Loading
// Only load e-commerce tracking on shop pages
add_action('wp_enqueue_scripts', 'conditional_ecommerce_scripts');
function conditional_ecommerce_scripts() {
if (is_woocommerce() || is_cart() || is_checkout() || is_account_page()) {
wp_enqueue_script('wc-ga4-tracking', get_stylesheet_directory_uri() . '/js/wc-ga4.js', array('jquery'), '1.0', true);
}
}
Defer Non-Critical Tracking
// Delay product impression tracking until page is interactive
if ('requestIdleCallback' in window) {
requestIdleCallback(() => {
// Fire impression events here
});
} else {
setTimeout(() => {
// Fire impression events here
}, 1000);
}
Troubleshooting
Purchases Not Tracking
- Check order confirmation page loads (not redirected away)
- Verify transaction ID is unique
- Ensure purchase event fires only once per order
- Check for JavaScript errors in console
Revenue Mismatch
- Compare WooCommerce reports with GA4
- Account for refunds, cancelled orders
- Verify tax and shipping are included correctly
- Check currency conversion if multi-currency store
See Tracking Troubleshooting Guide for detailed debugging.
Next Steps
Related Resources
- GA4 E-commerce Fundamentals - Universal concepts
- GTM for WooCommerce - Alternative tracking method
- WordPress Performance - Optimize tracking impact