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
Recommended Events for Ecommerce
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:
- Go to GA4 property > Configure > DebugView
- Open your store in another tab
- Perform actions (view product, add to cart, etc.)
- 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
- GA4 Ecommerce Tracking - Complete purchase tracking
- GTM Data Layer - Advanced event management
- Events Not Firing Troubleshooting - Debug issues