This guide covers implementing custom GA4 events in CS-Cart to track user interactions beyond basic page views and ecommerce transactions.
Overview
GA4 events help you understand how customers interact with your CS-Cart store. This guide focuses on non-ecommerce events (see Ecommerce Tracking for purchase tracking).
Automatic vs. Custom Events
Automatically Collected Events
GA4 automatically tracks these events with Enhanced Measurement:
- page_view - Page views
- scroll - Users who scroll to bottom (90%)
- click - Outbound link clicks
- view_search_results - Site search usage
- video_start, video_progress, video_complete - Video engagement
- file_download - File downloads
Recommended Events
Google recommends these events for ecommerce sites:
- search - Product/site search
- view_item_list - Product list views
- select_item - Product selection from list
- view_item - Product detail views
- add_to_wishlist - Wishlist additions
- add_to_cart - Cart additions (covered in ecommerce guide)
- begin_checkout - Checkout start (covered in ecommerce guide)
- purchase - Transaction completion (covered in ecommerce guide)
Custom Events
Create custom events for CS-Cart-specific interactions:
- Account registration
- Newsletter signup
- Product comparisons
- Wishlist interactions
- Customer reviews
- Quick view usage
- Filter applications
- Vendor page views (Multi-Vendor)
Implementation Methods
Method 1: Direct Event Implementation
Add event tracking directly in CS-Cart templates or JavaScript.
Basic Event Syntax
gtag('event', 'event_name', {
'parameter1': 'value1',
'parameter2': 'value2'
});
Method 2: Using Google Tag Manager
For easier management and testing, implement events via GTM (see GTM Setup).
Common CS-Cart Events
Site Search Tracking
Track when customers search your catalog:
In search results template (design/themes/[theme]/templates/blocks/product_filters/search.tpl):
{literal}
<script>
// Track search event
{/literal}
{if $search.q}
gtag('event', 'search', {
'search_term': '{$search.q|escape:javascript}',
'search_results': {$products|count}
});
{/if}
{literal}
</script>
{/literal}
Newsletter Signup
Track newsletter subscriptions:
// Add to newsletter subscription handler
document.addEventListener('DOMContentLoaded', function() {
const newsletterForm = document.querySelector('#subscribe_form');
if (newsletterForm) {
newsletterForm.addEventListener('submit', function(e) {
gtag('event', 'newsletter_signup', {
'method': 'footer_form'
});
});
}
});
Product Wishlist
Track wishlist additions:
// Hook into CS-Cart wishlist function
$(document).on('click', '.cm-add-to-wish-list', function() {
const productId = $(this).data('product-id');
const productName = $(this).data('product-name') || 'Unknown Product';
gtag('event', 'add_to_wishlist', {
'currency': 'USD', // Use your store currency
'value': parseFloat($(this).data('product-price')) || 0,
'items': [{
'item_id': productId,
'item_name': productName
}]
});
});
Product Compare
Track product comparison usage:
// Add to compare tracking
$(document).on('click', '.cm-add-to-comparison-list', function() {
const productId = $(this).data('product-id');
const productName = $(this).data('product-name');
gtag('event', 'add_to_compare', {
'items': [{
'item_id': productId,
'item_name': productName
}]
});
});
Customer Reviews
Track when customers submit reviews:
// In review form template
document.querySelector('.cm-submit-review')?.addEventListener('click', function() {
const productId = this.dataset.productId;
const rating = document.querySelector('input[name="rating"]:checked')?.value;
gtag('event', 'submit_review', {
'item_id': productId,
'rating': rating,
'review_type': 'product_review'
});
});
Quick View
Track product quick view usage:
// Hook into quick view modal
$(document).on('click', '.cm-dialog-opener.product-quick-view', function() {
const productId = $(this).data('product-id');
const productName = $(this).data('product-name');
gtag('event', 'quick_view', {
'item_id': productId,
'item_name': productName,
'engagement_type': 'quick_view'
});
});
User Registration
Track new account creation:
In registration success template (design/themes/[theme]/templates/views/checkout/components/profile_account.tpl):
{if $user_data.user_id && $runtime.controller == 'profiles' && $runtime.mode == 'add'}
{literal}
<script>
gtag('event', 'sign_up', {
'method': 'website_registration'
});
</script>
{/literal}
{/if}
Login Tracking
Track customer logins:
// After successful login
gtag('event', 'login', {
'method': 'email'
});
Product Filter Usage
Track catalog filter applications:
// Hook into filter application
$(document).on('click', '.cm-submit-filter', function() {
const filters = {};
$('.ty-product-filters__group input:checked').each(function() {
const filterName = $(this).attr('name');
filters[filterName] = $(this).val();
});
gtag('event', 'apply_filter', {
'filter_type': 'product_catalog',
'filters_applied': Object.keys(filters).length
});
});
Video Interaction
If you have product videos:
// YouTube player events
function onPlayerStateChange(event) {
const videoTitle = event.target.getVideoData().title;
if (event.data == YT.PlayerState.PLAYING) {
gtag('event', 'video_start', {
'video_title': videoTitle,
'video_provider': 'youtube'
});
}
}
Download Tracking
Track catalog/brochure downloads:
document.querySelectorAll('a[href$=".pdf"]').forEach(function(link) {
link.addEventListener('click', function(e) {
const fileName = this.getAttribute('href').split('/').pop();
gtag('event', 'file_download', {
'file_name': fileName,
'file_extension': 'pdf',
'link_url': this.href
});
});
});
Multi-Vendor Events
For CS-Cart Multi-Vendor marketplace:
Vendor Page Views
// On vendor storefront page
gtag('event', 'view_vendor', {
'vendor_id': '{$vendor_info.company_id}',
'vendor_name': '{$vendor_info.company|escape:javascript}'
});
Contact Vendor
// When customer contacts vendor
gtag('event', 'contact_vendor', {
'vendor_id': vendorId,
'contact_method': 'contact_form'
});
Advanced Event Tracking
Scroll Depth Tracking
Track how far users scroll on product pages:
let scrollTracked = {
'25': false,
'50': false,
'75': false,
'100': false
};
window.addEventListener('scroll', function() {
const scrollPercent = Math.round((window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100);
Object.keys(scrollTracked).forEach(function(threshold) {
if (scrollPercent >= threshold && !scrollTracked[threshold]) {
scrollTracked[threshold] = true;
gtag('event', 'scroll_depth', {
'percent_scrolled': threshold,
'page_type': 'product_page'
});
}
});
});
Time on Page
Track engaged users:
let timeOnPage = 0;
let trackingInterval = setInterval(function() {
timeOnPage += 10;
// Track at 30 seconds, 60 seconds, etc.
if (timeOnPage === 30 || timeOnPage === 60 || timeOnPage === 120) {
gtag('event', 'user_engagement', {
'engagement_time_msec': timeOnPage * 1000,
'page_location': window.location.href
});
}
}, 10000); // Every 10 seconds
// Clear on page unload
window.addEventListener('beforeunload', function() {
clearInterval(trackingInterval);
});
Error Tracking
Track JavaScript errors:
window.addEventListener('error', function(e) {
gtag('event', 'exception', {
'description': e.message,
'fatal': false
});
});
AJAX Error Tracking
Track AJAX failures in CS-Cart:
$(document).ajaxError(function(event, jqxhr, settings, thrownError) {
gtag('event', 'ajax_error', {
'error_message': thrownError,
'ajax_url': settings.url,
'fatal': false
});
});
Implementing Events with CS-Cart Hooks
Use CS-Cart's hook system for clean integration:
Create Custom Add-on
File: app/addons/custom_ga4_events/init.php
<?php
if (!defined('BOOTSTRAP')) { die('Access denied'); }
// Hook into product view
function fn_custom_ga4_events_get_product_data_post(&$product_id, &$field_list, &$join, &$auth, &$lang_code, &$condition, &$product_data) {
// Add GA4 event tracking data
$product_data['ga4_event_ready'] = true;
}
// Hook into cart operations
function fn_custom_ga4_events_add_to_cart_post(&$cart, &$product_id, &$product_data) {
// Trigger add_to_cart event (via JavaScript)
}
Template hook (design/themes/[theme]/templates/addons/custom_ga4_events/hooks/index/scripts.post.tpl):
{if $product.ga4_event_ready}
{literal}
<script>
// GA4 event tracking based on hook data
gtag('event', 'view_item', {
'items': [{
'item_id': '{/literal}{$product.product_id}{literal}',
'item_name': '{/literal}{$product.product|escape:javascript}{literal}'
}]
});
</script>
{/literal}
{/if}
Testing and Validation
Using GA4 DebugView
- Install Google Analytics Debugger Chrome extension
- Enable the extension
- In GA4, go to Admin → DebugView
- Trigger events on your CS-Cart store
- Verify events appear in DebugView with correct parameters
Using Browser Console
// Enable GA4 debug mode
gtag('config', 'G-XXXXXXXXXX', {
'debug_mode': true
});
// Check dataLayer
console.log(window.dataLayer);
Using Tag Assistant
- Install Tag Assistant
- Connect to your site
- Trigger events
- Verify events are captured correctly
Best Practices
1. Event Naming Conventions
Use Google's recommended event names when possible:
- Use lowercase and underscores:
add_to_cart, notaddToCart - Be descriptive but concise
- Follow GA4 naming conventions
2. Event Parameters
- Include relevant context with each event
- Use consistent parameter names
- Don't exceed 25 parameters per event
- Parameter names: max 40 characters
- Parameter values: max 100 characters
3. Data Quality
- Validate data before sending events
- Handle null/undefined values
- Ensure product IDs are consistent across events
- Use try/catch for error handling
4. Performance
- Don't block page load with event tracking
- Use event delegation for dynamic elements
- Avoid excessive event firing
- Debounce rapid events (scroll, resize)
5. Privacy Compliance
- Don't send personally identifiable information (PII)
- Respect cookie consent settings
- Anonymize sensitive data
- Follow GDPR/privacy regulations
Common Issues
Events Not Firing
Check:
- GA4 is properly installed
- Measurement ID is correct
- No JavaScript errors in console
- Event syntax is correct
- Elements exist in DOM
Duplicate Events
Solutions:
- Check for multiple event listeners
- Verify events aren't triggered in multiple places
- Use event delegation properly
- Remove conflicting plugins/add-ons
Missing Event Parameters
Solutions:
- Verify data is available when event fires
- Check variable scope
- Use default values for optional parameters
- Log events to console for debugging
Next Steps
- Configure Ecommerce Tracking - Track sales and transactions
- Implement GTM - Manage events via Tag Manager
- Troubleshooting Guide - Fix common tracking issues