BigCommerce GA4 Event Tracking
Track user interactions and custom events on your BigCommerce store using Google Analytics 4. This guide covers BigCommerce-specific events beyond basic ecommerce tracking.
Understanding GA4 Events on BigCommerce
Event Types
GA4 categorizes events into four types:
- Automatically Collected Events: Page views, first visits, session starts
- Enhanced Measurement Events: Scrolls, outbound clicks, site search, file downloads
- Recommended Events: BigCommerce ecommerce events (see Ecommerce Tracking)
- Custom Events: BigCommerce-specific interactions you define
BigCommerce Event Tracking Opportunities
Common interactions to track on BigCommerce stores:
- Product Interactions: Quick view clicks, image zoom, product video plays, variant selection
- Navigation: Faceted search usage, filter selections, category navigation
- User Engagement: Newsletter signups, wishlist additions, product reviews
- Cart Behavior: Apply coupon code, remove from cart, update quantities
- Customer Actions: Account creation, login/logout, address book updates
- Search Behavior: Site search queries, search result clicks, no results found
- Promotional: Banner clicks, promotional code usage, special offers
Implementation Methods
Method 1: Script Manager Events (Easiest)
Use Script Manager to add custom event tracking without modifying your theme.
Example: Track Newsletter Signups
Navigate to Script Manager:
- Go to Storefront > Script Manager
- Click Create a Script
Configure Script:
- Name: GA4 - Newsletter Signup Tracking
- Location: Footer
- Script Type: Script
- Pages: All pages
Add Event Tracking Code:
<script>
(function() {
// Wait for newsletter form to be available
document.addEventListener('DOMContentLoaded', function() {
var newsletterForm = document.querySelector('form[action*="subscribe"]') ||
document.querySelector('.newsletter-form') ||
document.querySelector('#newsletter-form');
if (newsletterForm) {
newsletterForm.addEventListener('submit', function(e) {
// Send event to GA4
if (typeof gtag !== 'undefined') {
gtag('event', 'newsletter_signup', {
'event_category': 'engagement',
'event_label': 'footer_newsletter',
'method': 'email'
});
}
});
}
});
})();
</script>
- Save and Activate
Example: Track Outbound Link Clicks
<script>
(function() {
document.addEventListener('DOMContentLoaded', function() {
// Track all external links
document.addEventListener('click', function(e) {
var target = e.target.closest('a');
if (target && target.href) {
var hostname = new URL(target.href).hostname;
var currentHostname = window.location.hostname;
// Check if link is external
if (hostname !== currentHostname && hostname !== '') {
if (typeof gtag !== 'undefined') {
gtag('event', 'click', {
'event_category': 'outbound',
'event_label': target.href,
'transport_type': 'beacon'
});
}
}
}
});
});
})();
</script>
Method 2: Stencil Theme Events (Advanced Control)
Implement event tracking directly in your Stencil theme for access to BigCommerce context data.
Tracking Product Quick View
File: templates/components/products/quick-view.html or add to product card template
<script>
(function() {
{{!-- Track quick view modal open --}}
var quickViewButtons = document.querySelectorAll('[data-quick-view]');
quickViewButtons.forEach(function(button) {
button.addEventListener('click', function() {
var productId = this.getAttribute('data-product-id');
var productName = this.getAttribute('data-product-name') || 'Unknown Product';
if (typeof gtag !== 'undefined') {
gtag('event', 'quick_view', {
'event_category': 'product_interaction',
'event_label': productName,
'product_id': productId,
'currency': '{{currency.code}}'
});
}
});
});
})();
</script>
Tracking Faceted Search Filters
File: templates/components/faceted-search/facets.html or assets/js/theme/global/faceted-search.js
// In your faceted search JavaScript
export default class FacetedSearch {
// ... existing code ...
onFilterChange(event) {
const filterType = event.target.getAttribute('data-filter-type');
const filterValue = event.target.value;
// Send to GA4
if (typeof gtag !== 'undefined') {
gtag('event', 'filter_applied', {
'event_category': 'product_discovery',
'filter_type': filterType,
'filter_value': filterValue
});
}
// ... rest of filter logic ...
}
}
Tracking Product Image Zoom
File: assets/js/theme/common/product-details.js
export default class ProductDetails {
constructor($scope, context) {
this.$scope = $scope;
this.context = context;
this.initImageZoom();
}
initImageZoom() {
this.$scope.on('click', '[data-zoom-image]', (event) => {
const productName = this.context.product.title;
const productId = this.context.product.id;
// Track image zoom
if (typeof gtag !== 'undefined') {
gtag('event', 'product_image_zoom', {
'event_category': 'product_interaction',
'event_label': productName,
'product_id': productId
});
}
});
}
}
Method 3: Using BigCommerce Storefront API
For headless BigCommerce or advanced implementations, use the Storefront API with event tracking.
// Fetch product details and track interaction
async function trackProductView(productId) {
try {
const response = await fetch(`/api/storefront/products/${productId}`, {
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json'
}
});
const product = await response.json();
if (typeof gtag !== 'undefined') {
gtag('event', 'view_item', {
'event_category': 'ecommerce',
'items': [{
'item_id': product.id,
'item_name': product.name,
'price': product.price,
'item_brand': product.brand?.name || '',
'item_category': product.categories?.[0]?.name || ''
}]
});
}
} catch (error) {
console.error('Error tracking product view:', error);
}
}
BigCommerce-Specific Event Examples
Track Coupon Code Application
// Track when customer applies a coupon code
document.addEventListener('DOMContentLoaded', function() {
const couponForm = document.querySelector('[data-coupon-code-form]') ||
document.querySelector('.coupon-form');
if (couponForm) {
couponForm.addEventListener('submit', function(e) {
const couponInput = this.querySelector('input[name="couponcode"]');
const couponCode = couponInput ? couponInput.value : 'unknown';
if (typeof gtag !== 'undefined') {
gtag('event', 'apply_coupon', {
'event_category': 'ecommerce',
'event_label': couponCode,
'coupon': couponCode
});
}
});
}
});
Track Product Review Submission
// Track product review form submission
document.addEventListener('DOMContentLoaded', function() {
const reviewForm = document.querySelector('[data-product-review-form]') ||
document.querySelector('.writeReview-form');
if (reviewForm) {
reviewForm.addEventListener('submit', function(e) {
const productId = this.getAttribute('data-product-id');
const rating = this.querySelector('input[name="rating"]:checked')?.value;
if (typeof gtag !== 'undefined') {
gtag('event', 'submit_review', {
'event_category': 'engagement',
'product_id': productId,
'rating': rating || 'not_specified'
});
}
});
}
});
Track Wishlist Actions
// Track add to wishlist
document.addEventListener('click', function(e) {
const wishlistButton = e.target.closest('[data-wishlist-add]');
if (wishlistButton) {
const productId = wishlistButton.getAttribute('data-product-id');
const productName = wishlistButton.getAttribute('data-product-name');
if (typeof gtag !== 'undefined') {
gtag('event', 'add_to_wishlist', {
'event_category': 'engagement',
'event_label': productName,
'items': [{
'item_id': productId,
'item_name': productName
}]
});
}
}
});
Track Account Creation
// Track account registration - add to account creation page
document.addEventListener('DOMContentLoaded', function() {
const registrationForm = document.querySelector('[data-create-account-form]') ||
document.querySelector('.create-account-form');
if (registrationForm) {
registrationForm.addEventListener('submit', function(e) {
if (typeof gtag !== 'undefined') {
gtag('event', 'sign_up', {
'event_category': 'engagement',
'method': 'email'
});
}
});
}
});
Track Site Search with No Results
// Track search queries that return no results
// Add to search results template or search JavaScript
document.addEventListener('DOMContentLoaded', function() {
const noResultsMessage = document.querySelector('.search-no-results') ||
document.querySelector('[data-search-no-results]');
if (noResultsMessage) {
const searchQuery = new URLSearchParams(window.location.search).get('search_query');
if (searchQuery && typeof gtag !== 'undefined') {
gtag('event', 'search', {
'search_term': searchQuery,
'search_results': 0
});
gtag('event', 'no_search_results', {
'event_category': 'search',
'event_label': searchQuery
});
}
}
});
Testing Event Tracking
Using Google Tag Assistant
- Install Tag Assistant Chrome Extension
- Navigate to your BigCommerce store
- Open Tag Assistant
- Perform tracked actions (newsletter signup, filter selection, etc.)
- Verify events appear in Tag Assistant with correct parameters
Using GA4 DebugView
- Enable debug mode by adding URL parameter:
?_ga_debug=1 - Or add this to Script Manager:
<script>
window['ga-disable-G-XXXXXXXXXX'] = false;
gtag('config', 'G-XXXXXXXXXX', {
'debug_mode': true
});
</script>
- Open Google Analytics
- Go to Admin > DebugView
- Perform actions on your store
- View events in real-time with full parameter details
Browser Console Verification
Add console logging for debugging:
if (typeof gtag !== 'undefined') {
gtag('event', 'custom_event', {
'event_category': 'test',
'event_callback': function() {
console.log('Event sent to GA4 successfully');
}
});
}
Event Naming Best Practices
Follow GA4 Conventions
- Use snake_case:
product_quick_view, notproductQuickVieworproduct-quick-view - Be descriptive:
newsletter_signupis better thansignup - Use recommended events when applicable: GA4 has predefined events for common ecommerce actions
- Limit custom parameters: Use up to 25 custom parameters per event
- Keep names under 40 characters: Event names should be concise
BigCommerce Event Naming Structure
Recommended naming convention:
{action}_{object}
Examples:
apply_couponview_quick_viewfilter_productssubmit_reviewcompare_products
Organizing Events by Category
Use event_category parameter to group related events:
- ecommerce: Purchase-related actions
- engagement: User engagement actions (newsletter, reviews, wishlist)
- navigation: Site navigation and discovery
- search: Search-related interactions
- product_interaction: Product-specific actions (zoom, quick view)
Performance Considerations
Avoid Tracking Too Frequently
Be cautious with high-frequency events:
// BAD: Tracks every scroll pixel
window.addEventListener('scroll', function() {
gtag('event', 'scroll'); // This will fire hundreds of times!
});
// GOOD: Track scroll milestones
let scrollMilestones = {25: false, 50: false, 75: false, 90: false};
window.addEventListener('scroll', function() {
const scrollPercent = (window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100;
Object.keys(scrollMilestones).forEach(function(milestone) {
if (scrollPercent >= milestone && !scrollMilestones[milestone]) {
scrollMilestones[milestone] = true;
gtag('event', 'scroll', {
'event_category': 'engagement',
'event_label': milestone + '%'
});
}
});
});
Use Event Throttling
For actions that can fire rapidly (resize, mousemove, input), throttle events:
function throttle(func, delay) {
let timeoutId;
let lastExecTime = 0;
return function(...args) {
const currentTime = Date.now();
if (currentTime - lastExecTime < delay) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
lastExecTime = currentTime;
func.apply(this, args);
}, delay);
} else {
lastExecTime = currentTime;
func.apply(this, args);
}
};
}
// Usage
const trackSearchInput = throttle(function(searchTerm) {
gtag('event', 'search_input', {
'search_term': searchTerm
});
}, 1000); // Limit to once per second
Troubleshooting
Events Not Firing
- Check gtag is loaded:
if (typeof gtag === 'undefined') {
console.error('gtag is not defined - GA4 not loaded');
}
Verify element selectors:
Check timing:
- Ensure events are attached after DOM loads
- Use
DOMContentLoadedor place scripts at end of<body>
Events Firing Multiple Times
- Check for duplicate event listeners
- Ensure event tracking code isn't included in both theme AND Script Manager
- Use event listener
onceoption for single-fire events:
element.addEventListener('click', function() {
// Event code
}, { once: true });