Master ecommerce analytics from beginner to expert with visual diagrams, code examples, and best practices for tracking customer journeys
Google Analytics 4 represents a fundamental shift in how web analytics works. According to Google's official GA4 documentation, the platform uses an event-based data model where every interaction is tracked as an event with parameters, replacing the session-based model of Universal Analytics.
Key characteristics of GA4 include:
Tealium is an enterprise-grade Customer Data Platform (CDP) and tag management solution. According to Tealium's official documentation, the platform consists of three main components:
Tag management for deploying marketing and analytics tags
Server-side data collection and distribution platform
Real-time CDP for identity resolution and audience segmentation
Tealium acts as the data orchestration layer between your Salesforce B2C Commerce storefront and GA4. This architecture provides flexibility, governance, and enhanced capabilities.
Understanding the B2C Commerce architecture is essential for implementing analytics correctly. For a comprehensive deep-dive into the platform's history, evolution, and architecture, see my detailed guide: Salesforce B2C Commerce Cloud Complete Guide.
For GA4 and Tealium implementation, focus on these critical integration points:
| Integration Point | Analytics Use Case |
|---|---|
| ISML Templates | Render utag_data object with page/product context |
| Controller Extensions | Add analytics data to ViewModels via module.superModule |
| Client-Side Scripts | Track dynamic events (add-to-cart, wishlist, AJAX actions) |
| PWA Kit / Composable | React components for data layer, virtual page views on route changes |
app_storefront_base. The documentation states: "You can customize SFRA without editing the app_storefront_base cartridge" - use server.extend and server.append to preserve upgrade compatibility and easily adopt security updates.While you can implement GA4 directly on your B2C Commerce storefront, using Tealium as an intermediary provides significant advantages for enterprise ecommerce operations.
| Aspect | Direct GA4 Implementation | Tealium + GA4 |
|---|---|---|
| Developer Dependency | Every change requires code deployment | Marketing can deploy tags independently |
| Version Control | Manual code versioning | Built-in version control with rollback |
| Testing | Requires staging environment | Preview mode for real-time testing |
| Multi-Vendor | Separate implementation per vendor | Single data layer, multiple outputs |
| Consent Management | Custom implementation needed | Built-in consent orchestration |
| Server-Side Tracking | Custom Measurement Protocol setup | EventStream connectors available |
Superior compliance management for GDPR, CCPA, and other privacy regulations
Works equally well with Adobe, Google, Meta, Salesforce ecosystems - not tied to any vendor
AudienceStream provides identity resolution and audience activation across channels
EventStream reduces client-side load and improves data accuracy by bypassing ad blockers
There are multiple ways to implement Tealium with GA4 on Salesforce B2C Commerce. The best approach depends on your storefront architecture and customization requirements.
The official Tealium integration for Salesforce Commerce Cloud provides a pre-built cartridge that handles most common scenarios.
plugin_tealium/
├── cartridge/
│ ├── scripts/
│ │ └── datalayer.js # Data layer configuration
│ └── templates/
│ └── default/
│ └── common/
│ ├── tealium.isml
│ └── datalayer.isml
For more control, create a custom plugin_tealium cartridge that extends the base functionality.
// plugin_tealium/cartridge/scripts/datalayer.js
var CONTEXT = {
GLOBAL: 'global',
PLP: 'plp',
PDP: 'pdp',
CART: 'cart',
CHECKOUT: 'checkout',
ORDER_CONFIRMATION: 'orderconfirmation'
};
function getDataLayer(context, data) {
var dataLayer = getGlobalData();
switch(context) {
case CONTEXT.PDP:
dataLayer = Object.assign(dataLayer, getProductData(data));
break;
case CONTEXT.CART:
dataLayer = Object.assign(dataLayer, getCartData(data));
break;
case CONTEXT.ORDER_CONFIRMATION:
dataLayer = Object.assign(dataLayer, getOrderData(data));
break;
}
return dataLayer;
}
function getGlobalData() {
return {
page_type: '',
site_currency: session.currency.currencyCode,
customer_logged_in: customer.authenticated ? '1' : '0',
customer_id: customer.authenticated ? customer.ID : ''
};
}
module.exports = {
CONTEXT: CONTEXT,
getDataLayer: getDataLayer
};
The data layer is rendered in ISML templates. Here's a typical implementation for the product detail page:
<!-- templates/default/product/productDetails.isml -->
<script>
var utag_data = {
page_type: "product",
page_name: "${pdict.product.productName}",
product_id: ["${pdict.product.id}"],
product_name: ["${pdict.product.productName}"],
product_brand: ["${pdict.product.brand}"],
product_category: ["${pdict.product.primaryCategory.displayName}"],
product_price: ["${pdict.product.price.sales.value}"],
product_sku: ["${pdict.product.id}"],
site_currency: "${session.currency.currencyCode}"
};
</script>
StringUtils.encodeJavascript().The data layer is the foundation of your analytics implementation. According to Tealium's data layer best practices, using a well-structured Universal Data Object (UDO) ensures consistent data across all vendors.
The utag_data object should contain all relevant information for the current page context:
// Base utag_data structure for ecommerce
var utag_data = {
// Page-level data
page_type: "product",
page_name: "Product Detail Page",
site_section: "products",
site_currency: "USD",
// User data
customer_logged_in: "1",
customer_id: "12345",
customer_type: "returning",
customer_email_hash: "a1b2c3d4...",
// Product data (arrays for multiple products)
product_id: ["SKU123"],
product_name: ["Blue T-Shirt"],
product_category: ["Apparel/Shirts/T-Shirts"],
product_brand: ["BrandName"],
product_price: ["29.99"],
product_quantity: ["1"],
product_variant: ["Large/Blue"],
// Transaction data (for purchase events)
order_id: "ORD-12345",
order_total: "89.99",
order_subtotal: "79.99",
order_tax: "5.00",
order_shipping: "5.00",
order_discount: "0.00",
order_coupon: ""
};
GA4 expects ecommerce data in a specific format. According to Google's ecommerce documentation, the items array is central to all ecommerce events:
// GA4 purchase event structure
dataLayer.push({
event: "purchase",
ecommerce: {
transaction_id: "T_12345",
value: 89.99,
tax: 5.00,
shipping: 5.00,
currency: "USD",
coupon: "SUMMER20",
items: [{
item_id: "SKU123",
item_name: "Blue T-Shirt",
item_brand: "BrandName",
item_category: "Apparel",
item_category2: "Shirts",
item_category3: "T-Shirts",
item_variant: "Large/Blue",
price: 29.99,
quantity: 1,
coupon: "",
discount: 0,
index: 0,
item_list_id: "related_products",
item_list_name: "Related Products"
}]
}
});
Based on GA4's recommended events reference, here are the required events for each page type:
| Page Type | GA4 Events | Required Parameters |
|---|---|---|
| Product Listing (PLP) | view_item_list, select_item | items array with item_list_id |
| Product Detail (PDP) | view_item | items array (item_id OR item_name required) |
| Cart | add_to_cart, remove_from_cart, view_cart | items array with quantity |
| Checkout | begin_checkout, add_shipping_info, add_payment_info | items array, value, currency |
| Order Confirmation | purchase | transaction_id, value, currency, items |
| Promotions | view_promotion, select_promotion | promotion_id, promotion_name |
Configuring Tealium iQ properly is essential for accurate GA4 tracking. According to Tealium's GA4 tag documentation, here's how to set up the integration.
Load rules determine when tags fire. According to Tealium's load rules documentation, use these patterns:
// Example load rules
- Load on All Pages: page_type EXISTS
- Product Pages Only: page_type EQUALS "product"
- Checkout Pages: page_type CONTAINS "checkout"
- Exclude Internal Traffic: user_ip NOT IN ["192.168.1.1", "10.0.0.1"]
- Consent Granted: consent_analytics EQUALS "granted"
According to Tealium's extensions documentation, extensions process data before tags fire:
| Extension | Purpose | Scope |
|---|---|---|
| E-Commerce Extension | Maps standard ecommerce variables (_corder, _csubtotal) | Before Load Rules |
| Set Data Values | Transform or create variables without code | Before Load Rules |
| JavaScript Code | Custom logic using the 'b' object | Tag Scope |
| Google Consent Mode | Handle consent signals for Google services | Pre Loader |
Understanding the execution order is critical for proper data transformation:
Tealium can pull data from multiple sources:
Mapping your data layer events to GA4's expected format is critical for accurate ecommerce reporting. According to Google's official GA4 ecommerce documentation, these are the recommended events for tracking the customer journey.
The tealium_event variable triggers specific GA4 events. Based on Tealium's GA4 tag documentation, here's how to map common ecommerce actions:
Use utag.link() to fire events dynamically (e.g., add to cart button click):
// Add to Cart button click handler
document.querySelector('.add-to-cart').addEventListener('click', function() {
utag.link({
tealium_event: "add_to_cart",
product_id: ["SKU123"],
product_name: ["Blue T-Shirt"],
product_price: ["29.99"],
product_quantity: ["1"],
product_category: ["Apparel/Shirts"],
product_brand: ["BrandName"]
});
});
// Remove from Cart
function removeFromCart(productId) {
utag.link({
tealium_event: "remove_from_cart",
product_id: [productId],
product_quantity: ["1"]
});
}
According to GA4's event reference, all ecommerce events require an items array. Tealium's E-Commerce Extension automatically transforms your data layer arrays into GA4's items format:
Server-side tracking via Tealium EventStream improves data accuracy by bypassing client-side limitations like ad blockers and browser restrictions.
According to Tealium's EventStream documentation, server-side tracking offers several advantages:
According to Tealium's GA4 Measurement Protocol connector documentation, configure these settings:
# Production endpoint
POST https://www.google-analytics.com/mp/collect?api_secret=XXX&measurement_id=G-XXX
# Validation/Debug endpoint (returns validation messages)
POST https://www.google-analytics.com/debug/mp/collect?api_secret=XXX&measurement_id=G-XXX
The best approach combines client-side and server-side tracking:
Privacy regulations like GDPR and CCPA require proper consent management before tracking users. Tealium provides built-in tools to handle consent orchestration across all your tags.
As of March 2024, Google requires Consent Mode v2 for compliance with EU regulations. According to Tealium's Google Consent Mode documentation, these signals must be implemented:
| Consent Signal | Purpose | Default State |
|---|---|---|
| ad_storage | Cookie storage for advertising | denied |
| analytics_storage | Cookie storage for analytics | denied |
| ad_user_data | User data sent to Google for advertising | denied |
| ad_personalization | Personalized advertising | denied |
Block all tags until consent is granted. Simple but may lose GA4's data modeling capabilities for non-consented users.
Load tags regardless of consent state, but send consent signals. Enables GA4's data modeling for non-consented users while remaining compliant.
According to Tealium's consent management documentation, configure consent in Tealium iQ:
// Default consent state (before user interaction)
gtag('consent', 'default', {
ad_storage: 'denied',
analytics_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied',
wait_for_update: 500 // Wait 500ms for consent update
});
// Update consent when user accepts
function updateConsent(analyticsConsent, adsConsent) {
gtag('consent', 'update', {
ad_storage: adsConsent ? 'granted' : 'denied',
analytics_storage: analyticsConsent ? 'granted' : 'denied',
ad_user_data: adsConsent ? 'granted' : 'denied',
ad_personalization: adsConsent ? 'granted' : 'denied'
});
}
| Regulation | Requirement | Implementation |
|---|---|---|
| GDPR (EU) | Explicit opt-in consent required | Basic or Advanced consent mode, block until granted |
| CCPA (California) | Right to opt-out, honor GPC signal | Opt-out mechanism, check navigator.globalPrivacyControl |
| DMA (EU) | Transparency, fair practices | Consent Mode v2 mandatory for EU users |
Proper debugging ensures your implementation is accurate before going live. Use these tools to validate your GA4 and Tealium setup.
According to Google's DebugView documentation, this real-time tool shows events as they arrive:
debug_mode: true to your events or use GA Debugger extension| Extension | Purpose | Best For |
|---|---|---|
| Tealium Tools | Inspect utag_data, events, tag firing | Tealium-specific debugging |
| Google Analytics Debugger | Loads debug version of GA code | Console logging |
| Omnibug | Multi-vendor tag debugger | Comparing multiple analytics |
| Tag Assistant | Google's official validation tool | GA4/GTM validation |
Test changes before publishing:
Use the Measurement Protocol validation endpoint:
# Send test event to validation endpoint
curl -X POST
'https://www.google-analytics.com/debug/mp/collect?api_secret=YOUR_SECRET&measurement_id=G-XXXXX'
-H 'Content-Type: application/json'
-d '{
"client_id": "123456.7890123456",
"events": [{
"name": "purchase",
"params": {
"transaction_id": "TEST-001",
"value": 99.99,
"currency": "USD"
}
}]
}'
# Response shows validation messages without storing data
Following these best practices will help you avoid common implementation mistakes and ensure accurate analytics data.
According to Tealium's official best practices:
product_unit_price)product_id: ["SKU1", "SKU2"] not comma-separated stringsis_ or has_ (e.g., is_logged_in)| Pitfall | Impact | Solution |
|---|---|---|
| Missing transaction_id | Purchase not recorded properly | Always include unique transaction ID |
| Missing currency | Revenue not calculated | Set currency on all monetary events |
| Duplicate events | Inflated metrics | Use single tracking method, avoid double-tagging |
| Wrong event names | Events not recognized by GA4 | Use exact GA4 event names (case-sensitive) |
| Timing issues | Missing data on fast interactions | Fire tag after dataLayer is populated |
| No referral exclusions | Broken attribution from payment gateways | Exclude PayPal, Stripe, auth providers |
module.superModule to chain functionality across cartridgesserver.append for middleware additionsapp_storefront_base directlyAccording to Tealium iQ best practices:
<body> after data layerutag.sync.js when absolutely necessaryReference guide for technical terms and abbreviations used throughout this article.
GA4 uses an event-based data model where every interaction is tracked as an event with parameters, while Universal Analytics used a session-based model with pageviews and hits. GA4 offers cross-platform tracking, machine learning insights, and is designed for a cookieless future with better privacy controls.
Tealium provides vendor-agnostic tag management, allowing marketing teams to deploy tags without code deployments. It offers superior consent management for GDPR/CCPA compliance, server-side tracking capabilities via EventStream, and a single data layer that can feed multiple analytics vendors simultaneously.
The recommended structure uses Tealium's Universal Data Object (UDO) format with utag_data containing page-level data (page_type, site_currency), user data (customer_id, customer_logged_in), product arrays (product_id, product_name, product_price), and transaction data (order_id, order_total) for purchase events.
Configure Tealium EventStream with the GA4 Measurement Protocol connector. You'll need an API Secret from GA4 Admin, the Measurement ID, and the client_id extracted from the _ga cookie. Server-side tracking improves data accuracy by bypassing ad blockers but cannot replace client-side tracking entirely.
Required events include: view_item_list and select_item for product listings, view_item for product detail pages, add_to_cart and remove_from_cart for cart actions, begin_checkout/add_shipping_info/add_payment_info for checkout steps, and purchase for order confirmation. Each event requires an items array with product details.