Google Tag Manager Setup for WooCommerce | OpsBlu Docs

Google Tag Manager Setup for WooCommerce

Complete guide to installing and configuring GTM on WooCommerce stores with data layer integration

Google Tag Manager (GTM) provides a flexible, code-free solution for managing analytics and marketing tags on WooCommerce stores. This guide covers WooCommerce-specific GTM implementation with proper data layer configuration.

Why Use GTM with WooCommerce?

Advantages

  • No code changes for new tags - Add GA4, Meta Pixel, TikTok without touching WordPress
  • Marketing team autonomy - Non-developers can manage tracking
  • Version control - Roll back tag changes easily
  • Built-in debugging - Preview mode for testing
  • WooCommerce data layer - Access product, cart, and order data
  • Trigger flexibility - Fire tags based on WooCommerce events

Disadvantages

  • Additional JavaScript load - GTM container adds ~50 KB
  • Learning curve - Requires GTM knowledge
  • Performance impact - Too many tags can slow site
  • Complexity - More moving parts than direct integration

Prerequisites

  1. Create GTM Account

    • Go to tagmanager.google.com
    • Create a new account and container
    • Select Web as container type
    • Copy your Container ID (format: GTM-XXXXXXX)
  2. Plan Your Implementation

    • Decide: Plugin vs. manual GTM installation
    • Identify tags needed (GA4, Meta Pixel, etc.)
    • Plan data layer structure for eCommerce

Best for: Most WooCommerce stores, automatic data layer, quick setup

Installation

  1. Install Plugin

    • Navigate to Plugins → Add New
    • Search for "Google Tag Manager for WordPress"
    • Install and activate GTM4WP by Thomas Geiger
  2. Enter Container ID

    • Go to Settings → Google Tag Manager
    • Enter your GTM Container ID (GTM-XXXXXXX)
    • Click Save Changes
  3. Enable WooCommerce Integration

    Settings → Google Tag Manager → Integration:
    
    ✓ WooCommerce integration
    ✓ Track classic eCommerce
    ✓ Track enhanced eCommerce
    ✓ Include remarketing features
    ✓ Track product impressions
    ✓ Track product clicks
    ✓ Track cart actions
    
  4. Configure Data Layer

    Settings → Google Tag Manager → Basic Data:
    
    ✓ Post/page data (post ID, title, author)
    ✓ Categories
    ✓ Tags
    ✓ Search data
    ✓ Logged in status
    ✓ User role
    
    WooCommerce Data:
    ✓ Product data
    ✓ Cart data
    ✓ Order data
    
  5. Advanced Settings

    Settings → Google Tag Manager → Advanced:
    
    Container code placement:
    - Codeless: Let the plugin add it (recommended)
    
    Blacklist/Whitelist tags:
    - Leave empty unless specific tags need restrictions
    
    Data layer variable naming:
    - Use default (dataLayer) unless you have conflicts
    
    Include user ID:
    ✓ Only if compliant with privacy policies
    

GTM4WP Data Layer Structure

The plugin automatically creates this data layer:

// Product page
dataLayer.push({
    'event': 'view_item',
    'ecommerce': {
        'items': [{
            'item_id': 'SKU123',
            'item_name': 'Product Name',
            'item_brand': 'Brand',
            'item_category': 'Category',
            'price': 99.99,
            'currency': 'USD'
        }]
    }
});

// Add to cart
dataLayer.push({
    'event': 'add_to_cart',
    'ecommerce': {
        'currency': 'USD',
        'value': 99.99,
        'items': [{
            'item_id': 'SKU123',
            'item_name': 'Product Name',
            'price': 99.99,
            'quantity': 1
        }]
    }
});

// Purchase
dataLayer.push({
    'event': 'purchase',
    'ecommerce': {
        'transaction_id': '12345',
        'value': 199.99,
        'tax': 15.00,
        'shipping': 10.00,
        'currency': 'USD',
        'items': [...]
    }
});

GTM4WP Custom Events

Add custom tracking beyond the plugin:

// Add custom data layer variable
add_filter('gtm4wp_compile_datalayer', 'custom_datalayer_data', 10, 1);
function custom_datalayer_data($data_layer) {
    // Add customer lifetime value
    if (is_user_logged_in()) {
        $customer = new WC_Customer(get_current_user_id());
        $data_layer['customerLTV'] = $customer->get_total_spent();
        $data_layer['customerOrderCount'] = $customer->get_order_count();
    }

    // Add cart count globally
    if (function_exists('WC')) {
        $data_layer['cartItemCount'] = WC()->cart->get_cart_contents_count();
        $data_layer['cartTotal'] = WC()->cart->get_cart_total();
    }

    return $data_layer;
}

Method 2: Manual GTM Installation

Best for: Developers, custom data layer, maximum control

Step 1: Add GTM Container Code

Using Child Theme:

// Add to child theme's functions.php
add_action('wp_head', 'add_gtm_head', 1);
function add_gtm_head() {
    if (current_user_can('manage_woocommerce')) {
        return; // Don't load for shop managers
    }
    ?>
    <!-- Google Tag Manager -->
    <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
    })(window,document,'script','dataLayer','GTM-XXXXXXX');</script>
    <!-- End Google Tag Manager -->
    <?php
}

add_action('wp_body_open', 'add_gtm_body');
function add_gtm_body() {
    if (current_user_can('manage_woocommerce')) {
        return;
    }
    ?>
    <!-- Google Tag Manager (noscript) -->
    <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
    height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
    <!-- End Google Tag Manager (noscript) -->
    <?php
}

Step 2: Create WooCommerce Data Layer

// Initialize data layer
add_action('wp_head', 'init_datalayer', 0);
function init_datalayer() {
    ?>
    <script>
        window.dataLayer = window.dataLayer || [];
    </script>
    <?php
}

// Product page data layer
add_action('woocommerce_after_single_product', 'product_datalayer');
function product_datalayer() {
    global $product;
    if (!$product) return;

    $product_data = array(
        'event' => 'view_item',
        'ecommerce' => array(
            'items' => array(
                array(
                    'item_id' => $product->get_sku() ? $product->get_sku() : $product->get_id(),
                    'item_name' => $product->get_name(),
                    'item_brand' => get_product_brand($product),
                    'item_category' => get_product_category($product),
                    'price' => (float) $product->get_price(),
                    'currency' => get_woocommerce_currency()
                )
            )
        )
    );
    ?>
    <script>
        dataLayer.push(<?php echo json_encode($product_data); ?>);
    </script>
    <?php
}

function get_product_category($product) {
    $categories = get_the_terms($product->get_id(), 'product_cat');
    return ($categories && !is_wp_error($categories)) ? $categories[0]->name : '';
}

function get_product_brand($product) {
    $brands = get_the_terms($product->get_id(), 'product_brand');
    return ($brands && !is_wp_error($brands)) ? $brands[0]->name : '';
}

Step 3: Track Add to Cart (AJAX)

// Add to cart data layer (AJAX compatible)
add_action('wp_footer', 'addtocart_datalayer');
function addtocart_datalayer() {
    ?>
    <script>
        jQuery(document.body).on('added_to_cart', function(event, fragments, cart_hash, $button) {
            var productId = $button.data('product_id');
            var productName = $button.data('product_name') || $button.attr('aria-label');
            var quantity = $button.data('quantity') || 1;

            dataLayer.push({
                'event': 'add_to_cart',
                'ecommerce': {
                    'currency': '<?php echo get_woocommerce_currency(); ?>',
                    'items': [{
                        'item_id': productId,
                        'item_name': productName,
                        'quantity': quantity
                    }]
                }
            });
        });
    </script>
    <?php
}

Step 4: Track Purchase

// Purchase data layer
add_action('woocommerce_thankyou', 'purchase_datalayer', 10, 1);
function purchase_datalayer($order_id) {
    if (!$order_id) return;

    // Prevent duplicate tracking
    if (get_post_meta($order_id, '_gtm_purchase_tracked', true)) {
        return;
    }

    $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_sku() : $product->get_id(),
            'item_name' => $item->get_name(),
            'item_category' => get_product_category($product),
            'price' => (float) ($item->get_total() / $item->get_quantity()),
            'quantity' => $item->get_quantity()
        );
    }

    $purchase_data = array(
        'event' => 'purchase',
        'ecommerce' => array(
            'transaction_id' => $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
        )
    );
    ?>
    <script>
        dataLayer.push(<?php echo json_encode($purchase_data); ?>);
    </script>
    <?php

    update_post_meta($order_id, '_gtm_purchase_tracked', true);
}

Configuring Tags in GTM

1. Set Up GA4 Configuration Tag

  1. Create New Tag in GTM

    • Tag Type: Google Analytics: GA4 Configuration
    • Measurement ID: Your GA4 G-XXXXXXXXXX
    • Trigger: All Pages
  2. Enable Enhanced Measurement

    • Check Send ecommerce events

2. Set Up GA4 Event Tags

Create tags for WooCommerce events:

Add to Cart Event:

Tag Type: Google Analytics: GA4 Event
Configuration Tag: [Your GA4 Config Tag]
Event Name: add_to_cart

Event Parameters:
- currency: {{dlv - ecommerce.currency}}
- value: {{dlv - ecommerce.value}}
- items: {{dlv - ecommerce.items}}

Trigger: Custom Event = add_to_cart

Purchase Event:

Tag Type: Google Analytics: GA4 Event
Configuration Tag: [Your GA4 Config Tag]
Event Name: purchase

Event Parameters:
- transaction_id: {{dlv - ecommerce.transaction_id}}
- value: {{dlv - ecommerce.value}}
- tax: {{dlv - ecommerce.tax}}
- shipping: {{dlv - ecommerce.shipping}}
- currency: {{dlv - ecommerce.currency}}
- items: {{dlv - ecommerce.items}}

Trigger: Custom Event = purchase

3. Create Data Layer Variables

For each eCommerce parameter, create a Data Layer Variable:

Variable Type: Data Layer Variable
Data Layer Variable Name: ecommerce.transaction_id
Variable Name: dlv - ecommerce.transaction_id

Create variables for:

  • ecommerce.currency
  • ecommerce.value
  • ecommerce.items
  • ecommerce.transaction_id
  • ecommerce.tax
  • ecommerce.shipping

4. Set Up Triggers

Add to Cart Trigger:

Trigger Type: Custom Event
Event name: add_to_cart

Purchase Trigger:

Trigger Type: Custom Event
Event name: purchase

Product View Trigger:

Trigger Type: Custom Event
Event name: view_item

WooCommerce-Specific GTM Features

Track Cart Fragments

WooCommerce uses AJAX cart fragments - ensure tracking works:

// Ensure GTM tracking works with cart fragments
add_filter('woocommerce_add_to_cart_fragments', 'gtm_cart_fragments');
function gtm_cart_fragments($fragments) {
    // GTM4WP handles this automatically
    // For manual implementations, add data layer push here
    return $fragments;
}

Track Variable Products

// Push variation selection to data layer
jQuery('.variations_form').on('found_variation', function(event, variation) {
    dataLayer.push({
        'event': 'view_item_variant',
        'ecommerce': {
            'items': [{
                'item_id': variation.sku || variation.variation_id,
                'item_variant': Object.values(variation.attributes).join(', '),
                'price': variation.display_price
            }]
        }
    });
});

Testing GTM Implementation

1. Use GTM Preview Mode

  1. In GTM, click Preview
  2. Enter your WooCommerce site URL
  3. Complete actions (view product, add to cart, purchase)
  4. Verify:
    • Tags fire correctly
    • Data layer contains expected values
    • No errors in console

2. Check Data Layer in Console

// View entire data layer
console.table(dataLayer);

// View specific events
dataLayer.filter(item => item.event === 'purchase');

// View eCommerce data
dataLayer.filter(item => item.ecommerce);

3. Verify in GA4 Real-Time

  • Navigate to GA4 → Reports → Realtime
  • Perform WooCommerce actions
  • Confirm events appear

Performance Optimization

Delay GTM Loading

// Delay GTM for better performance
add_action('wp_footer', 'delay_gtm_loading', 99);
function delay_gtm_loading() {
    ?>
    <script>
        // Delay GTM until user interaction
        let gtmLoaded = false;
        const loadGTM = () => {
            if (gtmLoaded) return;
            gtmLoaded = true;

            (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
            new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
            j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
            'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
            })(window,document,'script','dataLayer','GTM-XXXXXXX');
        };

        // Load on interaction or after 3 seconds
        ['scroll', 'click', 'touchstart'].forEach(event => {
            window.addEventListener(event, loadGTM, {once: true, passive: true});
        });
        setTimeout(loadGTM, 3000);
    </script>
    <?php
}

Common Issues

GTM Container Not Loading

Cause: Missing wp_head() or wp_body_open() in theme Solution: Add hooks to theme or use plugin

Data Layer Empty

Cause: Data layer pushed before GTM loads Solution: Initialize data layer before GTM container

Events Fire Twice

Cause: Multiple GTM implementations (plugin + manual) Solution: Choose one method and remove the other

AJAX Cart Not Tracked

Cause: Not listening to WooCommerce AJAX events Solution: Use added_to_cart jQuery event

Next Steps