PrestaShop GA4 Event Tracking | Blue Frog Docs

PrestaShop GA4 Event Tracking

Implement and customize Google Analytics 4 event tracking for PrestaShop user interactions, product views, and custom events.

PrestaShop GA4 Event Tracking

Track user interactions and behaviors on your PrestaShop store with Google Analytics 4 events. This guide covers standard GA4 events, PrestaShop-specific implementations, and custom event creation.

Standard GA4 Events for PrestaShop

Automatically Tracked Events

When GA4 is properly installed, these events track automatically:

1. page_view

  • Fires on every page load
  • Includes page title, location, referrer
  • No additional configuration needed

2. session_start

  • Fires when a new session begins
  • Automatic with GA4 global tag
  • Used for session metrics

3. first_visit

  • Fires only once per user (first time visiting)
  • Helps track new vs. returning users
  • Automatic with GA4

These events should be implemented for complete ecommerce tracking:

Event Name When to Fire PrestaShop Page/Action
view_item_list Category/search results viewed Category pages, search results
select_item Product clicked from list Product link clicked
view_item Product detail page viewed Product page load
add_to_cart Item added to cart Add to cart button click
remove_from_cart Item removed from cart Remove from cart action
view_cart Cart page viewed Shopping cart page load
begin_checkout Checkout initiated Checkout page load
add_shipping_info Shipping method selected Shipping step completed
add_payment_info Payment method selected Payment step
purchase Order completed Order confirmation page

Implementing Events with PrestaShop Hooks

PrestaShop's hook system provides perfect trigger points for GA4 events.

Hook-Based Event Implementation

Module Structure for Event Tracking:

<?php
// modules/customga4events/customga4events.php

class CustomGA4Events extends Module
{
    public function __construct()
    {
        $this->name = 'customga4events';
        $this->tab = 'analytics_stats';
        $this->version = '1.0.0';
        $this->author = 'Your Name';

        parent::__construct();

        $this->displayName = $this->l('GA4 Event Tracking');
        $this->description = $this->l('Track GA4 events using PrestaShop hooks');
    }

    public function install()
    {
        return parent::install()
            && $this->registerHook('displayHeader')
            && $this->registerHook('displayFooterProduct')
            && $this->registerHook('actionCartSave')
            && $this->registerHook('displayShoppingCart')
            && $this->registerHook('displayOrderConfirmation')
            && $this->registerHook('actionProductSearchAfter');
    }

    // Header: Load event tracking scripts
    public function hookDisplayHeader($params)
    {
        // Add GA4 event tracking helper functions
        $this->context->controller->addJS($this->_path . 'views/js/ga4-events.js');
    }

    // Product Page: view_item event
    public function hookDisplayFooterProduct($params)
    {
        $product = $params['product'];

        $this->context->smarty->assign(array(
            'ga4_event' => 'view_item',
            'ga4_product' => $this->formatProduct($product)
        ));

        return $this->display(__FILE__, 'views/templates/hook/product-view.tpl');
    }

    // Cart Action: add_to_cart or remove_from_cart
    public function hookActionCartSave($params)
    {
        // This hook doesn't allow template return
        // Store event data in session for JavaScript to retrieve
        if (isset($params['cart']) && isset($params['id_product'])) {
            $cart_action = $params['cart']->getLastProduct();

            $event_data = array(
                'event' => 'add_to_cart',
                'product' => $this->formatProduct($cart_action)
            );

            // Store in cookie/session for JS retrieval
            $this->context->cookie->ga4_event = json_encode($event_data);
        }
    }

    // Shopping Cart: view_cart event
    public function hookDisplayShoppingCart($params)
    {
        $cart = $this->context->cart;
        $products = $cart->getProducts(true);

        $items = array();
        foreach ($products as $product) {
            $items[] = $this->formatProduct($product);
        }

        $this->context->smarty->assign(array(
            'ga4_event' => 'view_cart',
            'ga4_items' => $items,
            'ga4_cart_value' => $cart->getOrderTotal()
        ));

        return $this->display(__FILE__, 'views/templates/hook/cart-view.tpl');
    }

    // Search: view_item_list event
    public function hookActionProductSearchAfter($params)
    {
        $products = $params['products'];
        $search_term = $params['search_query'];

        $items = array();
        foreach ($products as $product) {
            $items[] = $this->formatProduct($product);
        }

        $this->context->smarty->assign(array(
            'ga4_event' => 'view_item_list',
            'ga4_items' => $items,
            'ga4_list_name' => 'search_results',
            'ga4_search_term' => $search_term
        ));

        return $this->display(__FILE__, 'views/templates/hook/search-results.tpl');
    }

    // Helper: Format product for GA4
    private function formatProduct($product)
    {
        return array(
            'item_id' => isset($product['id_product']) ? $product['id_product'] : $product->id,
            'item_name' => isset($product['name']) ? $product['name'] : $product->name,
            'item_category' => $this->getProductCategory($product),
            'item_brand' => $this->getProductBrand($product),
            'price' => isset($product['price']) ? $product['price'] : $product->getPrice(),
            'quantity' => isset($product['quantity']) ? $product['quantity'] : 1
        );
    }

    private function getProductCategory($product)
    {
        $id_product = isset($product['id_product']) ? $product['id_product'] : $product->id;
        $category = new Category(Product::getDefaultCategory($id_product), $this->context->language->id);
        return $category->name;
    }

    private function getProductBrand($product)
    {
        $id_manufacturer = isset($product['id_manufacturer']) ? $product['id_manufacturer'] : 0;
        if ($id_manufacturer > 0) {
            $manufacturer = new Manufacturer($id_manufacturer);
            return $manufacturer->name;
        }
        return '';
    }
}

Event Templates

Product View Template:

{* modules/customga4events/views/templates/hook/product-view.tpl *}
<script>
  // Fire view_item event
  gtag('event', 'view_item', {
    currency: '{$currency.iso_code|escape:'javascript':'UTF-8'}',
    value: {$ga4_product.price|floatval},
    items: [{
      item_id: '{$ga4_product.item_id|escape:'javascript':'UTF-8'}',
      item_name: '{$ga4_product.item_name|escape:'javascript':'UTF-8'}',
      item_category: '{$ga4_product.item_category|escape:'javascript':'UTF-8'}',
      item_brand: '{$ga4_product.item_brand|escape:'javascript':'UTF-8'}',
      price: {$ga4_product.price|floatval},
      quantity: 1
    }]
  });
</script>

Cart View Template:

{* modules/customga4events/views/templates/hook/cart-view.tpl *}
<script>
  // Fire view_cart event
  gtag('event', 'view_cart', {
    currency: '{$currency.iso_code|escape:'javascript':'UTF-8'}',
    value: {$ga4_cart_value|floatval},
    items: [
      {foreach from=$ga4_items item=item}
      {
        item_id: '{$item.item_id|escape:'javascript':'UTF-8'}',
        item_name: '{$item.item_name|escape:'javascript':'UTF-8'}',
        item_category: '{$item.item_category|escape:'javascript':'UTF-8'}',
        price: {$item.price|floatval},
        quantity: {$item.quantity|intval}
      }{if !$item@last},{/if}
      {/foreach}
    ]
  });
</script>

JavaScript Event Tracking

For client-side interactions that don't have server-side hooks.

Add to Cart Button Click

Enhanced Product Page Script:

// modules/customga4events/views/js/ga4-events.js

// Add to Cart tracking
document.addEventListener('DOMContentLoaded', function() {

  // Track add to cart button clicks
  var addToCartButtons = document.querySelectorAll('[data-button-action="add-to-cart"]');

  addToCartButtons.forEach(function(button) {
    button.addEventListener('click', function(e) {
      // Get product data from page
      var productData = getProductDataFromPage();

      if (typeof gtag !== 'undefined') {
        gtag('event', 'add_to_cart', {
          currency: prestashop.currency.iso_code,
          value: parseFloat(productData.price),
          items: [{
            item_id: productData.id,
            item_name: productData.name,
            item_category: productData.category,
            price: parseFloat(productData.price),
            quantity: parseInt(productData.quantity)
          }]
        });
      }
    });
  });

  // Track remove from cart
  var removeButtons = document.querySelectorAll('.cart-item-remove, .remove-from-cart');

  removeButtons.forEach(function(button) {
    button.addEventListener('click', function(e) {
      var cartItem = this.closest('.cart-item, .product-line-grid');
      var productData = getProductDataFromCartItem(cartItem);

      if (typeof gtag !== 'undefined') {
        gtag('event', 'remove_from_cart', {
          currency: prestashop.currency.iso_code,
          value: parseFloat(productData.price),
          items: [{
            item_id: productData.id,
            item_name: productData.name,
            price: parseFloat(productData.price),
            quantity: parseInt(productData.quantity)
          }]
        });
      }
    });
  });

  // Track product clicks in listings
  var productLinks = document.querySelectorAll('.product-miniature a.product-thumbnail, .product-miniature a.product-title');

  productLinks.forEach(function(link) {
    link.addEventListener('click', function(e) {
      var productMiniature = this.closest('.product-miniature');
      var productData = getProductDataFromMiniature(productMiniature);

      if (typeof gtag !== 'undefined') {
        gtag('event', 'select_item', {
          item_list_name: getCurrentListName(),
          items: [{
            item_id: productData.id,
            item_name: productData.name,
            item_category: productData.category,
            price: parseFloat(productData.price)
          }]
        });
      }
    });
  });

  // Begin checkout tracking
  var checkoutButtons = document.querySelectorAll('[data-link-action="proceed-to-checkout"], .checkout-button');

  checkoutButtons.forEach(function(button) {
    button.addEventListener('click', function(e) {
      var cartValue = getCartTotal();
      var cartItems = getCartItems();

      if (typeof gtag !== 'undefined') {
        gtag('event', 'begin_checkout', {
          currency: prestashop.currency.iso_code,
          value: parseFloat(cartValue),
          items: cartItems
        });
      }
    });
  });
});

// Helper functions
function getProductDataFromPage() {
  return {
    id: prestashop.page.id_product || document.querySelector('[data-product-id]')?.dataset.productId,
    name: document.querySelector('h1.product-title')?.textContent.trim(),
    category: document.querySelector('.breadcrumb .category')?.textContent.trim(),
    price: document.querySelector('[data-product-price]')?.dataset.productPrice ||
           document.querySelector('.product-price .current-price-value')?.textContent.replace(/[^0-9.]/g, ''),
    quantity: document.querySelector('#quantity_wanted')?.value || 1
  };
}

function getProductDataFromCartItem(cartItem) {
  return {
    id: cartItem.dataset.idProduct || cartItem.querySelector('[data-id-product]')?.dataset.idProduct,
    name: cartItem.querySelector('.product-name, .label')?.textContent.trim(),
    price: cartItem.querySelector('.product-price, .price')?.textContent.replace(/[^0-9.]/g, ''),
    quantity: cartItem.querySelector('.qty input, .product-quantity')?.value || 1
  };
}

function getProductDataFromMiniature(miniature) {
  return {
    id: miniature.dataset.idProduct,
    name: miniature.querySelector('.product-title')?.textContent.trim(),
    category: miniature.dataset.category || '',
    price: miniature.querySelector('.product-price .price')?.textContent.replace(/[^0-9.]/g, '')
  };
}

function getCurrentListName() {
  if (document.body.classList.contains('category')) {
    return 'category_' + (prestashop.page.id_category || 'unknown');
  } else if (document.body.classList.contains('search')) {
    return 'search_results';
  } else if (document.body.classList.contains('index')) {
    return 'homepage';
  }
  return 'product_list';
}

function getCartTotal() {
  var totalElement = document.querySelector('.cart-total .value, .cart-summary-line.cart-total .value');
  return totalElement ? totalElement.textContent.replace(/[^0-9.]/g, '') : '0';
}

function getCartItems() {
  var items = [];
  var cartItems = document.querySelectorAll('.cart-item, .product-line-grid');

  cartItems.forEach(function(item) {
    var productData = getProductDataFromCartItem(item);
    items.push({
      item_id: productData.id,
      item_name: productData.name,
      price: parseFloat(productData.price),
      quantity: parseInt(productData.quantity)
    });
  });

  return items;
}

Custom Events for PrestaShop

Newsletter Signup Event

// Track newsletter subscriptions
document.addEventListener('DOMContentLoaded', function() {
  var newsletterForm = document.querySelector('#newsletter-form, .block_newsletter form');

  if (newsletterForm) {
    newsletterForm.addEventListener('submit', function(e) {
      if (typeof gtag !== 'undefined') {
        gtag('event', 'newsletter_signup', {
          method: 'footer_form',
          page_location: window.location.href
        });
      }
    });
  }
});

Account Creation Event

// In custom module - hookActionCustomerAccountAdd
public function hookActionCustomerAccountAdd($params)
{
    $customer = $params['newCustomer'];

    $this->context->smarty->assign(array(
        'ga4_customer_id' => $customer->id,
        'ga4_customer_email' => $customer->email
    ));

    return $this->display(__FILE__, 'views/templates/hook/account-created.tpl');
}
{* Template for account creation event *}
<script>
  gtag('event', 'sign_up', {
    method: 'prestashop_registration'
  });
</script>

Wishlist Events

// Track wishlist add/remove
document.addEventListener('click', function(e) {
  // Add to wishlist
  if (e.target.matches('.wishlist-button-add, [data-action="add-to-wishlist"]')) {
    var productId = e.target.dataset.productId || e.target.closest('[data-id-product]').dataset.idProduct;
    var productName = e.target.dataset.productName || document.querySelector('.product-title').textContent.trim();

    if (typeof gtag !== 'undefined') {
      gtag('event', 'add_to_wishlist', {
        currency: prestashop.currency.iso_code,
        items: [{
          item_id: productId,
          item_name: productName
        }]
      });
    }
  }

  // Remove from wishlist
  if (e.target.matches('.wishlist-button-remove, [data-action="remove-from-wishlist"]')) {
    var productId = e.target.dataset.productId;

    if (typeof gtag !== 'undefined') {
      gtag('event', 'remove_from_wishlist', {
        items: [{
          item_id: productId
        }]
      });
    }
  }
}, false);

Product Review/Rating Event

// Track when users submit reviews
var reviewForm = document.querySelector('.product-review-form, #new_comment_form');

if (reviewForm) {
  reviewForm.addEventListener('submit', function(e) {
    var productId = document.querySelector('[data-product-id]')?.dataset.productId;
    var rating = document.querySelector('input[name="rating"]:checked')?.value;

    if (typeof gtag !== 'undefined') {
      gtag('event', 'review_submitted', {
        item_id: productId,
        rating: rating
      });
    }
  });
}

Compare Products Event

// Track product comparison
document.addEventListener('click', function(e) {
  if (e.target.matches('[data-action="add-to-compare"], .compare-button')) {
    var productId = e.target.dataset.productId || e.target.closest('[data-id-product]').dataset.idProduct;

    if (typeof gtag !== 'undefined') {
      gtag('event', 'add_to_compare', {
        item_id: productId
      });
    }
  }
}, false);

Multi-Store Event Tracking

Adding Store Context to Events

// Add shop ID to all events
if (typeof gtag !== 'undefined') {
  // Set shop ID as custom dimension
  gtag('set', {
    'shop_id': prestashop.shop.id,
    'shop_name': prestashop.shop.name
  });

  // Or add to each event
  function trackEventWithStore(eventName, params) {
    params = params || {};
    params.shop_id = prestashop.shop.id;
    params.shop_name = prestashop.shop.name;
    gtag('event', eventName, params);
  }
}

Testing and Debugging Events

Using GA4 DebugView

Enable Debug Mode:

// Add to GA4 config
gtag('config', 'G-XXXXXXXXXX', {
  'debug_mode': true
});

Or install Google Analytics Debugger Chrome extension.

Check Events in Real-Time:

  1. Go to GA4 property > Configure > DebugView
  2. Open your store in another tab
  3. Perform actions (view product, add to cart, etc.)
  4. Verify events appear in DebugView with correct parameters

Browser Console Testing

// Test event firing from console
gtag('event', 'test_event', {
  'test_parameter': 'test_value'
});

// Check dataLayer
console.log(window.dataLayer);

Common Event Issues

Events Not Firing:

  • Check if gtag.js is loaded: typeof gtag !== 'undefined'
  • Verify Measurement ID is correct
  • Check browser console for errors
  • Ensure PrestaShop cache is cleared

Duplicate Events:

  • Multiple modules tracking same event
  • Both theme and module tracking
  • Event firing on page load AND user interaction

Missing Parameters:

  • Product data not available in context
  • Currency not set in PrestaShop
  • Category/brand missing from product

Next Steps

// SYS.FOOTER