BigCommerce GA4 Ecommerce Tracking
Implement comprehensive ecommerce tracking for your BigCommerce store using Google Analytics 4. This guide covers the complete customer journey from product discovery to purchase.
GA4 Ecommerce Events Overview
GA4 tracks the ecommerce funnel using these recommended events:
| Event | Description | When to Trigger |
|---|---|---|
view_item_list |
User views product list | Category pages, search results |
select_item |
User clicks product from list | Product card clicks |
view_item |
User views product details | Product page load |
add_to_cart |
Product added to cart | Add to cart button click |
remove_from_cart |
Product removed from cart | Remove from cart action |
view_cart |
User views shopping cart | Cart page load |
begin_checkout |
User starts checkout | Checkout initiation |
add_payment_info |
Payment method selected | Payment step in checkout |
add_shipping_info |
Shipping method selected | Shipping step in checkout |
purchase |
Transaction completed | Order confirmation page |
Implementation Prerequisites
Before implementing ecommerce tracking:
- GA4 base tracking installed (see GA4 Setup)
- Stencil theme access (recommended) or Script Manager access
- Store admin access to configure checkout scripts
- BigCommerce plan that supports checkout script injection (Plus, Pro, or Enterprise)
Method 1: Stencil Theme Implementation (Recommended)
This method provides full access to BigCommerce context data for accurate ecommerce tracking.
Step 1: Track Product Impressions (view_item_list)
File: templates/pages/category.html or templates/pages/search.html
{{#if products}}
<script>
(function() {
// Wait for gtag to be available
if (typeof gtag === 'undefined') return;
// Build items array from BigCommerce product data
var items = [
{{#each products}}
{
item_id: '{{id}}',
item_name: '{{name}}',
item_brand: '{{brand.name}}',
item_category: '{{category}}',
price: {{price.without_tax.value}},
currency: '{{../currency.code}}',
index: {{@index}}
}{{#unless @last}},{{/unless}}
{{/each}}
];
// Send view_item_list event
gtag('event', 'view_item_list', {
item_list_id: '{{category.id}}',
item_list_name: '{{category.name}}',
items: items
});
})();
</script>
{{/if}}
Step 2: Track Product Clicks (select_item)
File: templates/components/products/card.html
<article class="card"
data-product-id="{{id}}"
data-event-type="product-click">
<a href="{{url}}"
data-product-name="{{name}}"
data-product-price="{{price.without_tax.value}}"
data-product-brand="{{brand.name}}"
data-product-category="{{category}}"
onclick="trackProductClick(this)">
{{!-- Product card content --}}
</a>
</article>
<script>
function trackProductClick(element) {
if (typeof gtag === 'undefined') return;
var productData = {
item_id: element.closest('[data-product-id]').getAttribute('data-product-id'),
item_name: element.getAttribute('data-product-name'),
item_brand: element.getAttribute('data-product-brand'),
item_category: element.getAttribute('data-product-category'),
price: parseFloat(element.getAttribute('data-product-price')) || 0
};
gtag('event', 'select_item', {
item_list_id: 'product_list',
item_list_name: 'Product List',
items: [productData]
});
}
</script>
Step 3: Track Product Views (view_item)
File: templates/pages/product.html
{{#with product}}
<script>
(function() {
if (typeof gtag === 'undefined') return;
// Extract product data from BigCommerce context
var product = {
item_id: '{{id}}',
item_name: '{{title}}',
item_brand: '{{brand.name}}',
{{#if category}}
item_category: '{{category}}',
{{/if}}
price: {{price.without_tax.value}},
currency: '{{../currency.code}}'
};
// Send view_item event
gtag('event', 'view_item', {
currency: '{{../currency.code}}',
value: {{price.without_tax.value}},
items: [product]
});
})();
</script>
{{/with}}
Step 4: Track Add to Cart (add_to_cart)
File: assets/js/theme/common/cart-item-details.js or add inline to product page
import $ from 'jquery';
export default function trackAddToCart(productId, quantity = 1) {
// Fetch product details from BigCommerce Storefront API
fetch(`/api/storefront/products/${productId}`)
.then(response => response.json())
.then(product => {
if (typeof gtag !== 'undefined') {
gtag('event', 'add_to_cart', {
currency: product.currency || 'USD',
value: product.price.without_tax.value * quantity,
items: [{
item_id: product.id.toString(),
item_name: product.name,
item_brand: product.brand?.name || '',
item_category: product.categories?.[0]?.name || '',
price: product.price.without_tax.value,
quantity: quantity
}]
});
}
})
.catch(error => console.error('Error tracking add to cart:', error));
}
// Hook into BigCommerce add to cart event
$('body').on('cart-item-add', function(event, productId, quantity) {
trackAddToCart(productId, quantity);
});
Step 5: Track Remove from Cart (remove_from_cart)
File: templates/components/cart/content.html or cart JavaScript
// Track remove from cart
document.addEventListener('click', function(e) {
const removeButton = e.target.closest('[data-cart-remove]');
if (removeButton) {
const cartItem = removeButton.closest('[data-cart-item]');
const itemId = cartItem?.getAttribute('data-item-id');
const itemName = cartItem?.getAttribute('data-item-name');
const itemPrice = parseFloat(cartItem?.getAttribute('data-item-price')) || 0;
const itemQuantity = parseInt(cartItem?.getAttribute('data-item-quantity')) || 1;
if (typeof gtag !== 'undefined' && itemId) {
gtag('event', 'remove_from_cart', {
currency: 'USD', // Or pull from context
value: itemPrice * itemQuantity,
items: [{
item_id: itemId,
item_name: itemName,
price: itemPrice,
quantity: itemQuantity
}]
});
}
}
});
Step 6: Track View Cart (view_cart)
File: templates/pages/cart.html
{{#if cart.items}}
<script>
(function() {
if (typeof gtag === 'undefined') return;
var cartItems = [
{{#each cart.items}}
{
item_id: '{{id}}',
item_name: '{{name}}',
item_brand: '{{brand}}',
price: {{price}},
quantity: {{quantity}}
}{{#unless @last}},{{/unless}}
{{/each}}
];
gtag('event', 'view_cart', {
currency: '{{cart.currency.code}}',
value: {{cart.grand_total}},
items: cartItems
});
})();
</script>
{{/if}}
Step 7: Track Checkout Initiation (begin_checkout)
For Optimized One-Page Checkout (Plus, Pro, Enterprise):
Go to Settings > Checkout, add to Header Scripts:
<script>
(function() {
// Only fire on checkout page, not confirmation
if (window.location.pathname.includes('/checkout') &&
!window.location.pathname.includes('/order-confirmation')) {
// Poll for checkout data to become available
var checkoutDataInterval = setInterval(function() {
// BigCommerce exposes checkout data in window object
if (typeof BCData !== 'undefined' && BCData.checkout) {
clearInterval(checkoutDataInterval);
var checkout = BCData.checkout;
var items = checkout.cart.lineItems.physicalItems.map(function(item) {
return {
item_id: item.productId.toString(),
item_name: item.name,
price: item.salePrice,
quantity: item.quantity
};
});
if (typeof gtag !== 'undefined') {
gtag('event', 'begin_checkout', {
currency: checkout.cart.currency.code,
value: checkout.cart.baseAmount,
items: items
});
}
}
}, 500);
// Stop checking after 10 seconds
setTimeout(function() {
clearInterval(checkoutDataInterval);
}, 10000);
}
})();
</script>
Step 8: Track Purchase (purchase)
File: templates/pages/order-confirmation.html
{{#if order}}
<script>
(function() {
if (typeof gtag === 'undefined') return;
// Build transaction items array
var items = [
{{#each order.items}}
{
item_id: '{{product_id}}',
item_name: '{{name}}',
price: {{price}},
quantity: {{quantity}}
}{{#unless @last}},{{/unless}}
{{/each}}
];
// Send purchase event
gtag('event', 'purchase', {
transaction_id: '{{order.id}}',
value: {{order.total}},
tax: {{order.tax_total}},
shipping: {{order.shipping_cost}},
currency: '{{order.currency.code}}',
coupon: '{{#if order.coupon_code}}{{order.coupon_code}}{{/if}}',
items: items
});
})();
</script>
{{/if}}
Alternative: Use Conversion Tracking Script (All Plans):
In Settings > Analytics, add to Conversion Tracking Code:
<script>
if (typeof gtag !== 'undefined') {
gtag('event', 'purchase', {
transaction_id: '%%ORDER_ID%%',
value: %%ORDER_AMOUNT%%,
tax: %%ORDER_TAX%%,
shipping: %%ORDER_SHIPPING%%,
currency: '%%GLOBAL_CurrencyCode%%',
items: [
%%GLOBAL_ProductCartItems%%
]
});
}
</script>
Note: BigCommerce's %%GLOBAL_*%% variables are limited. For full purchase tracking, use order confirmation page template or upgrade to a plan with checkout script access.
Method 2: Script Manager Implementation (Limited)
For stores without Stencil access, you can implement basic ecommerce tracking via Script Manager, but with limitations.
Track Add to Cart via Script Manager
<script>
(function() {
document.addEventListener('DOMContentLoaded', function() {
// Listen for BigCommerce cart events
document.addEventListener('click', function(e) {
const addToCartBtn = e.target.closest('[data-button-type="add-cart"]') ||
e.target.closest('.button--add-to-cart');
if (addToCartBtn) {
// Limited data available without Stencil context
// You would need to scrape product details from DOM
const productCard = addToCartBtn.closest('[data-product-id]');
if (productCard && typeof gtag !== 'undefined') {
const productId = productCard.getAttribute('data-product-id');
gtag('event', 'add_to_cart', {
items: [{
item_id: productId,
item_name: 'Product ' + productId // Limited info
}]
});
}
}
});
});
})();
</script>
Limitations:
- Cannot easily access structured product data
- Requires DOM scraping which is fragile
- Stencil theme method is strongly recommended
Tracking with BigCommerce Apps
Using Native BigCommerce Google Analytics App
The official app provides automatic ecommerce tracking but with limitations:
What's Tracked:
- Product impressions (limited data)
- Add to cart
- Checkout steps
- Purchases
Limitations:
- Cannot customize event structure
- Limited access to custom parameters
- No control over data layer
- Basic implementation only
When to Use:
- Quick setup for basic stores
- No development resources available
- Standard tracking requirements
When to Avoid:
- Need custom ecommerce events
- Advanced tracking requirements
- Custom dimensions or parameters
- Integration with GTM data layer
Enhanced Ecommerce Best Practices
1. Include Product Variants
When tracking variants, include variant information:
gtag('event', 'add_to_cart', {
items: [{
item_id: '{{product.id}}',
item_name: '{{product.name}}',
item_variant: '{{selectedVariant.name}}', // e.g., "Red / Large"
price: {{selectedVariant.price}},
quantity: quantity
}]
});
2. Track Product Categories Hierarchically
Use category hierarchy for better reporting:
{
item_id: '{{product.id}}',
item_name: '{{product.name}}',
item_category: 'Apparel', // Level 1
item_category2: 'Men', // Level 2
item_category3: 'T-Shirts', // Level 3
item_category4: 'Graphic Tees' // Level 4
}
3. Use Consistent Currency
Always include currency in ecommerce events:
gtag('event', 'purchase', {
currency: '{{currency.code}}', // USD, EUR, GBP, etc.
value: {{order.total}},
// ... other parameters
});
4. Include Promotion Tracking
Track promotional banners and special offers:
// View promotion
gtag('event', 'view_promotion', {
creative_name: 'Summer Sale Banner',
creative_slot: 'homepage_hero',
promotion_id: 'SUMMER2024',
promotion_name: 'Summer Sale',
items: [/* products in promotion */]
});
// Select promotion
gtag('event', 'select_promotion', {
creative_name: 'Summer Sale Banner',
creative_slot: 'homepage_hero',
promotion_id: 'SUMMER2024',
promotion_name: 'Summer Sale'
});
Testing Ecommerce Tracking
1. Use GA4 DebugView
Enable debug mode:
gtag('config', 'G-XXXXXXXXXX', {
'debug_mode': true
});
Then go to Admin > DebugView in GA4 to see events in real-time with full parameters.
2. Test Complete Funnel
Walk through the entire customer journey:
- View category page → Check
view_item_list - Click product → Check
select_item - View product page → Check
view_item - Add to cart → Check
add_to_cart - View cart → Check
view_cart - Start checkout → Check
begin_checkout - Complete purchase → Check
purchase
3. Verify in E-commerce Reports
After 24-48 hours, check:
- Reports > Monetization > Ecommerce purchases
- Reports > Monetization > Purchase journey
- Explorations > Funnel exploration (create custom funnel)
4. Validate Transaction IDs
Ensure transaction_id in purchase events matches actual order IDs from BigCommerce:
- Complete test order
- Note order number from BigCommerce admin
- Check GA4 DebugView or Realtime report
- Verify transaction_id matches order number
Troubleshooting
Purchase Events Firing Twice
Cause: Purchase tracking implemented in multiple places (theme + Script Manager + app)
Solution:
- Remove duplicate implementations
- Choose ONE method: theme template OR conversion tracking script OR native app
- Clear cache and test again
Missing Product Data in Events
Cause: Incorrect context access or timing issues
Solution:
- Verify
\{\{product\}\}context is available in template - Use browser console to inspect
BCDataobject - Ensure events fire after product data loads
- Use Storefront API to fetch missing data
Ecommerce Events Not in GA4
Cause: Events sent but not recognized as ecommerce
Solution:
- Verify event names match GA4 recommended events exactly (
purchase, notPurchaseorcompleted_purchase) - Include required parameters (
itemsarray,currency,value) - Check item objects have required fields (
item_id,item_name)
Checkout Tracking Not Working
Cause: BigCommerce plan limitations or script placement
Solution:
- Verify you're on Plus, Pro, or Enterprise plan
- Check Scripts are in Settings > Checkout > Header Scripts
- Ensure scripts load before checkout page renders
- Test in incognito mode to avoid caching issues
Advanced: Server-Side Tracking
For more accurate tracking that bypasses ad blockers:
Using BigCommerce Webhooks
Set up webhook in BigCommerce:
- Go to Settings > API > Webhooks
- Create webhook for
store/order/created
Send to GA4 Measurement Protocol:
// Your webhook endpoint (Node.js example)
app.post('/webhooks/order-created', async (req, res) => {
const order = req.body.data;
// Send to GA4 Measurement Protocol
await fetch(`https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXXXXX&api_secret=YOUR_API_SECRET`, {
method: 'POST',
body: JSON.stringify({
client_id: order.customer_id.toString(),
events: [{
name: 'purchase',
params: {
transaction_id: order.id.toString(),
value: order.total,
currency: order.currency_code,
tax: order.tax_total,
shipping: order.shipping_cost,
items: order.products.map(item => ({
item_id: item.product_id.toString(),
item_name: item.name,
price: item.price,
quantity: item.quantity
}))
}
}]
})
});
res.status(200).send('OK');
});