Enhanced eCommerce tracking provides comprehensive product performance data, revenue attribution, and customer journey insights for WooCommerce stores. This guide covers the complete implementation from product impressions to purchase completion.
What is Enhanced Ecommerce?
Enhanced eCommerce tracking captures the full customer journey:
- Product Impressions - Which products customers see
- Product Clicks - Which products generate interest
- Product Detail Views - Deep engagement with specific products
- Add/Remove from Cart - Cart behavior and abandonment signals
- Checkout Process - Multi-step checkout funnel
- Purchases - Revenue, products sold, transaction details
- Refunds - Returns and revenue adjustments
Complete WooCommerce Enhanced Ecommerce Implementation
1. Product Impressions (Shop/Category Pages)
Track all products displayed to customers:
// Track product impressions on archive pages
add_action('woocommerce_after_shop_loop', 'track_product_impressions');
function track_product_impressions() {
global $wp_query;
if (!$wp_query->have_posts()) return;
$items = array();
$position = 1;
// Loop through displayed products
foreach ($wp_query->posts as $post) {
$product = wc_get_product($post->ID);
if (!$product) continue;
$items[] = array(
'item_id' => $product->get_sku() ? $product->get_sku() : $product->get_id(),
'item_name' => $product->get_name(),
'item_category' => get_product_primary_category($product),
'item_category2' => get_product_secondary_category($product),
'item_brand' => get_product_brand($product),
'price' => (float) $product->get_price(),
'index' => $position,
'quantity' => 1
);
$position++;
}
if (empty($items)) return;
// Determine list name
$list_name = get_current_list_name();
?>
<script>
gtag('event', 'view_item_list', {
item_list_id: '<?php echo sanitize_title($list_name); ?>',
item_list_name: '<?php echo esc_js($list_name); ?>',
items: <?php echo json_encode($items); ?>
});
</script>
<?php
}
function get_product_primary_category($product) {
$categories = get_the_terms($product->get_id(), 'product_cat');
if ($categories && !is_wp_error($categories)) {
$primary = $categories[0];
return $primary->name;
}
return '';
}
function get_product_secondary_category($product) {
$categories = get_the_terms($product->get_id(), 'product_cat');
if ($categories && !is_wp_error($categories) && count($categories) > 1) {
return $categories[1]->name;
}
return '';
}
function get_product_brand($product) {
// If using a brand taxonomy or attribute
$brands = get_the_terms($product->get_id(), 'product_brand');
if ($brands && !is_wp_error($brands)) {
return $brands[0]->name;
}
return '';
}
function get_current_list_name() {
if (is_shop()) {
return 'Shop Page';
} elseif (is_product_category()) {
$category = get_queried_object();
return 'Category: ' . $category->name;
} elseif (is_product_tag()) {
$tag = get_queried_object();
return 'Tag: ' . $tag->name;
} elseif (is_search()) {
return 'Search Results';
} elseif (is_front_page()) {
return 'Homepage';
}
return 'Product List';
}
2. Product Clicks
Track when customers click on products:
// Add product click tracking via JavaScript
add_action('wp_footer', 'track_product_select_items');
function track_product_select_items() {
if (!is_shop() && !is_product_category() && !is_product_tag() && !is_front_page()) {
return;
}
?>
<script>
document.addEventListener('DOMContentLoaded', function() {
var listName = '<?php echo esc_js(get_current_list_name()); ?>';
// Track product link clicks
document.querySelectorAll('.products .product a.woocommerce-LoopProduct-link, .products .product a.woocommerce-loop-product__link').forEach(function(link, index) {
link.addEventListener('click', function(e) {
var product = this.closest('.product');
var productName = product.querySelector('.woocommerce-loop-product__title')?.textContent || 'Unknown';
var productId = product.querySelector('[data-product_id]')?.getAttribute('data-product_id') || '';
var priceElement = product.querySelector('.price .amount, .price');
var productPrice = priceElement ? parseFloat(priceElement.textContent.replace(/[^0-9.-]+/g, '')) : 0;
gtag('event', 'select_item', {
item_list_id: listName.toLowerCase().replace(/[^a-z0-9]+/g, '_'),
item_list_name: listName,
items: [{
item_id: productId,
item_name: productName,
price: productPrice,
index: index
}]
});
});
});
});
</script>
<?php
}
3. Product Detail Views
Track single product page views:
// Track product detail views
add_action('woocommerce_after_single_product', 'track_product_detail_view');
function track_product_detail_view() {
global $product;
if (!$product) return;
$item_data = array(
'item_id' => $product->get_sku() ? $product->get_sku() : $product->get_id(),
'item_name' => $product->get_name(),
'item_category' => get_product_primary_category($product),
'item_category2' => get_product_secondary_category($product),
'item_brand' => get_product_brand($product),
'price' => (float) $product->get_price(),
'quantity' => 1
);
// Add variant info for variable products
if ($product->is_type('variable')) {
$item_data['item_variant'] = 'Variable Product';
}
?>
<script>
gtag('event', 'view_item', {
currency: '<?php echo get_woocommerce_currency(); ?>',
value: <?php echo (float) $product->get_price(); ?>,
items: [<?php echo json_encode($item_data); ?>]
});
</script>
<?php
}
4. Add to Cart (AJAX-Compatible)
Track cart additions with full product data:
// Track add to cart on single product pages
add_action('woocommerce_after_add_to_cart_button', 'track_add_to_cart_button');
function track_add_to_cart_button() {
global $product;
?>
<script>
jQuery(document).ready(function($) {
$('form.cart').on('submit', function(e) {
var quantity = parseInt($('input.qty').val()) || 1;
var productData = {
item_id: '<?php echo $product->get_sku() ? $product->get_sku() : $product->get_id(); ?>',
item_name: '<?php echo esc_js($product->get_name()); ?>',
item_category: '<?php echo esc_js(get_product_primary_category($product)); ?>',
price: <?php echo (float) $product->get_price(); ?>,
quantity: quantity
};
gtag('event', 'add_to_cart', {
currency: '<?php echo get_woocommerce_currency(); ?>',
value: productData.price * quantity,
items: [productData]
});
});
});
</script>
<?php
}
// Track AJAX add to cart from shop pages
add_action('wp_footer', 'track_ajax_add_to_cart_enhanced');
function track_ajax_add_to_cart_enhanced() {
if (is_shop() || is_product_category() || is_product_tag()) {
?>
<script>
jQuery(document.body).on('added_to_cart', function(event, fragments, cart_hash, $button) {
var product = $button.closest('.product');
var productId = $button.data('product_id');
var quantity = $button.data('quantity') || 1;
var productName = product.find('.woocommerce-loop-product__title').text() || $button.attr('aria-label');
var priceText = product.find('.price .amount').first().text();
var price = parseFloat(priceText.replace(/[^0-9.-]+/g, ''));
gtag('event', 'add_to_cart', {
currency: '<?php echo get_woocommerce_currency(); ?>',
value: price * quantity,
items: [{
item_id: productId,
item_name: productName,
price: price,
quantity: quantity
}]
});
});
</script>
<?php
}
}
5. Remove from Cart
Track cart item removals:
// Track remove from cart
add_action('woocommerce_remove_cart_item', 'track_remove_from_cart_enhanced', 10, 2);
function track_remove_from_cart_enhanced($cart_item_key, $cart) {
$cart_item = $cart->get_cart_item($cart_item_key);
if (!$cart_item) return;
$product = $cart_item['data'];
?>
<script>
gtag('event', 'remove_from_cart', {
currency: '<?php echo get_woocommerce_currency(); ?>',
value: <?php echo (float) $product->get_price() * $cart_item['quantity']; ?>,
items: [{
item_id: '<?php echo $product->get_sku() ? $product->get_sku() : $product->get_id(); ?>',
item_name: '<?php echo esc_js($product->get_name()); ?>',
price: <?php echo (float) $product->get_price(); ?>,
quantity: <?php echo $cart_item['quantity']; ?>
}]
});
</script>
<?php
}
6. View Cart
Track cart page views with all items:
// Track cart view
add_action('woocommerce_after_cart', 'track_view_cart_enhanced');
function track_view_cart_enhanced() {
$cart = WC()->cart;
if ($cart->is_empty()) {
return;
}
$items = array();
foreach ($cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
$items[] = array(
'item_id' => $product->get_sku() ? $product->get_sku() : $product->get_id(),
'item_name' => $product->get_name(),
'item_category' => get_product_primary_category($product),
'price' => (float) $product->get_price(),
'quantity' => $cart_item['quantity']
);
}
?>
<script>
gtag('event', 'view_cart', {
currency: '<?php echo get_woocommerce_currency(); ?>',
value: <?php echo $cart->get_cart_contents_total(); ?>,
items: <?php echo json_encode($items); ?>
});
</script>
<?php
}
7. Begin Checkout
Track checkout initiation:
// Track begin checkout
add_action('woocommerce_before_checkout_form', 'track_begin_checkout_enhanced');
function track_begin_checkout_enhanced() {
// Prevent duplicate tracking
static $tracked = false;
if ($tracked) return;
$tracked = true;
$cart = WC()->cart;
$items = array();
foreach ($cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
$item_data = array(
'item_id' => $product->get_sku() ? $product->get_sku() : $product->get_id(),
'item_name' => $product->get_name(),
'item_category' => get_product_primary_category($product),
'price' => (float) $product->get_price(),
'quantity' => $cart_item['quantity']
);
// Add variation data if applicable
if (isset($cart_item['variation']) && !empty($cart_item['variation'])) {
$item_data['item_variant'] = implode(', ', $cart_item['variation']);
}
$items[] = $item_data;
}
?>
<script>
gtag('event', 'begin_checkout', {
currency: '<?php echo get_woocommerce_currency(); ?>',
value: <?php echo $cart->get_total('raw'); ?>,
coupon: '<?php echo implode(', ', $cart->get_applied_coupons()); ?>',
items: <?php echo json_encode($items); ?>
});
</script>
<?php
}
8. Add Shipping Info
Track shipping method selection:
// Track shipping info
add_action('woocommerce_checkout_order_processed', 'track_add_shipping_info_enhanced', 10, 1);
function track_add_shipping_info_enhanced($order_id) {
$order = wc_get_order($order_id);
$shipping_method = $order->get_shipping_method();
if (!$shipping_method) return;
$items = array();
foreach ($order->get_items() as $item) {
$product = $item->get_product();
$items[] = array(
'item_id' => $product->get_sku() ? $product->get_sku() : $product->get_id(),
'item_name' => $item->get_name(),
'price' => (float) ($item->get_total() / $item->get_quantity()),
'quantity' => $item->get_quantity()
);
}
?>
<script>
gtag('event', 'add_shipping_info', {
currency: '<?php echo $order->get_currency(); ?>',
value: <?php echo $order->get_total(); ?>,
shipping_tier: '<?php echo esc_js($shipping_method); ?>',
items: <?php echo json_encode($items); ?>
});
</script>
<?php
}
9. Add Payment Info
Track payment method selection:
// Track payment info
add_action('woocommerce_checkout_order_processed', 'track_add_payment_info_enhanced', 10, 1);
function track_add_payment_info_enhanced($order_id) {
$order = wc_get_order($order_id);
$payment_method = $order->get_payment_method_title();
$items = array();
foreach ($order->get_items() as $item) {
$product = $item->get_product();
$items[] = array(
'item_id' => $product->get_sku() ? $product->get_sku() : $product->get_id(),
'item_name' => $item->get_name(),
'price' => (float) ($item->get_total() / $item->get_quantity()),
'quantity' => $item->get_quantity()
);
}
?>
<script>
gtag('event', 'add_payment_info', {
currency: '<?php echo $order->get_currency(); ?>',
value: <?php echo $order->get_total(); ?>,
payment_type: '<?php echo esc_js($payment_method); ?>',
items: <?php echo json_encode($items); ?>
});
</script>
<?php
}
10. Purchase Event
Track completed purchases on the thank you page:
// Track purchase completion
add_action('woocommerce_thankyou', 'track_purchase_enhanced', 10, 1);
function track_purchase_enhanced($order_id) {
if (!$order_id) return;
// Prevent duplicate tracking
if (get_post_meta($order_id, '_ga4_purchase_tracked', true)) {
return;
}
$order = wc_get_order($order_id);
// Build items array
$items = array();
foreach ($order->get_items() as $item) {
$product = $item->get_product();
$item_data = array(
'item_id' => $product->get_sku() ? $product->get_sku() : $product->get_id(),
'item_name' => $item->get_name(),
'item_category' => get_product_primary_category($product),
'item_brand' => get_product_brand($product),
'price' => (float) ($item->get_total() / $item->get_quantity()),
'quantity' => $item->get_quantity()
);
// Add variation data if applicable
if ($product->is_type('variation')) {
$item_data['item_variant'] = $product->get_attribute_summary();
}
$items[] = $item_data;
}
// Get coupon codes
$coupons = $order->get_coupon_codes();
$coupon_string = !empty($coupons) ? implode(', ', $coupons) : '';
// Determine new vs returning customer
$customer_email = $order->get_billing_email();
$customer_orders = wc_get_orders(array(
'billing_email' => $customer_email,
'status' => array('wc-completed', 'wc-processing'),
'limit' => -1
));
$is_new_customer = count($customer_orders) <= 1 ? 'new' : 'returning';
?>
<script>
gtag('event', 'purchase', {
transaction_id: '<?php echo $order->get_order_number(); ?>',
value: <?php echo $order->get_total(); ?>,
tax: <?php echo $order->get_total_tax(); ?>,
shipping: <?php echo $order->get_shipping_total(); ?>,
currency: '<?php echo $order->get_currency(); ?>',
coupon: '<?php echo esc_js($coupon_string); ?>',
affiliation: '<?php echo esc_js(get_bloginfo('name')); ?>',
customer_type: '<?php echo $is_new_customer; ?>',
payment_method: '<?php echo esc_js($order->get_payment_method_title()); ?>',
shipping_method: '<?php echo esc_js($order->get_shipping_method()); ?>',
items: <?php echo json_encode($items); ?>
});
</script>
<?php
// Mark as tracked
update_post_meta($order_id, '_ga4_purchase_tracked', true);
}
11. Refund Tracking
Track refunds and returns:
// Track refunds
add_action('woocommerce_order_refunded', 'track_refund_enhanced', 10, 2);
function track_refund_enhanced($order_id, $refund_id) {
$order = wc_get_order($order_id);
$refund = wc_get_order($refund_id);
if (!$refund) return;
$items = array();
foreach ($refund->get_items() as $item) {
$product_id = $item->get_product_id();
$product = wc_get_product($product_id);
if ($product) {
$items[] = array(
'item_id' => $product->get_sku() ? $product->get_sku() : $product->get_id(),
'item_name' => $item->get_name(),
'price' => (float) abs($item->get_total() / $item->get_quantity()),
'quantity' => abs($item->get_quantity())
);
}
}
?>
<script>
gtag('event', 'refund', {
transaction_id: '<?php echo $order->get_order_number(); ?>',
value: <?php echo abs($refund->get_total()); ?>,
currency: '<?php echo $order->get_currency(); ?>',
items: <?php echo json_encode($items); ?>
});
</script>
<?php
}
Handling Variable Products
Track Variation Selection
// Add variation tracking to product pages
add_action('woocommerce_after_add_to_cart_button', 'track_variation_selection_enhanced');
function track_variation_selection_enhanced() {
global $product;
if (!$product->is_type('variable')) return;
?>
<script>
jQuery('.variations_form').on('found_variation', function(event, variation) {
var variationData = {
item_id: variation.sku || variation.variation_id,
item_name: '<?php echo esc_js($product->get_name()); ?>',
item_variant: Object.values(variation.attributes).filter(v => v).join(', '),
price: parseFloat(variation.display_price)
};
gtag('event', 'view_item', {
currency: '<?php echo get_woocommerce_currency(); ?>',
value: variationData.price,
items: [variationData]
});
});
</script>
<?php
}
Complete Data Layer Approach (Alternative)
For GTM users, push complete data to the data layer:
// Push complete eCommerce data to dataLayer
add_action('wp_footer', 'push_ecommerce_datalayer', 99);
function push_ecommerce_datalayer() {
global $product;
// Product pages
if (is_product() && $product) {
?>
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'event': 'productDetailView',
'ecommerce': {
'detail': {
'products': [{
'id': '<?php echo $product->get_sku() ? $product->get_sku() : $product->get_id(); ?>',
'name': '<?php echo esc_js($product->get_name()); ?>',
'price': <?php echo (float) $product->get_price(); ?>,
'brand': '<?php echo esc_js(get_product_brand($product)); ?>',
'category': '<?php echo esc_js(get_product_primary_category($product)); ?>'
}]
}
}
});
</script>
<?php
}
}
Testing Enhanced Ecommerce
1. Complete Purchase Flow Test
- Browse shop page → Verify
view_item_list - Click product → Verify
select_item - View product details → Verify
view_item - Add to cart → Verify
add_to_cart - View cart → Verify
view_cart - Begin checkout → Verify
begin_checkout - Complete purchase → Verify
purchase
2. GA4 Reports to Check
After 24-48 hours:
- Monetization → Ecommerce Purchases - Revenue and transactions
- Monetization → Item List Name & Item Name - Product performance
- Monetization → Item Promotion - Product discovery paths
- Exploration → Funnel Exploration - Create custom checkout funnel
3. Real-Time Validation
Use GA4 → Reports → Realtime → Events to verify events fire immediately.
Best Practices
- Use SKUs when available - More reliable than product IDs
- Track deduplication - Prevent duplicate purchase events on page refresh
- Include all item parameters - Categories, brands, variants for rich analysis
- Test AJAX thoroughly - WooCommerce uses AJAX extensively
- Handle variable products - Track variations separately
- Monitor data quality - Regular audits of revenue and transaction counts
Next Steps
- Event Tracking - Custom WooCommerce events
- GTM Data Layer - Alternative implementation
- Troubleshoot Tracking - Debug eCommerce events