Shopify Tracking Issues
Platform-specific guides for diagnosing and fixing analytics and tracking issues on Shopify.
Common Issues
Events Not Firing
Debug why analytics events aren't being captured on Shopify.
Shopify-Specific Tracking Challenges
Shopify's Liquid templating system and strict checkout restrictions create unique tracking scenarios that require platform-specific solutions.
Platform Code Injection Points
Shopify offers multiple locations for adding tracking code, each with different behaviors:
Theme Customization Code Injection:
- Settings → Online Store → Preferences → Additional scripts (Checkout only, deprecated for checkout.liquid in Plus)
- Theme.liquid head section (all pages except checkout for Basic/Standard plans)
- Additional content & scripts sections in Theme Editor
- Custom Liquid sections for granular control
Shopify Analytics Script Management:
// Available in theme.liquid head
{% if template contains 'product' %}
<script>
// Product-specific tracking
console.log('Product:', {{ product | json }});
</script>
{% endif %}
Code Location Restrictions by Plan:
| Location | Basic/Standard | Shopify Plus |
|---|---|---|
| theme.liquid | Available | Available |
| checkout.liquid | Not available | Available |
| Customer events (Web Pixels) | Available | Available |
| Shopify Scripts | Not available | Available |
Checkout Tracking Limitations
Non-Plus Plans:
- Cannot edit checkout.liquid
- Must use Additional Scripts (loads after checkout completion)
- Cannot track individual checkout steps
- Limited access to checkout data
Shopify Plus:
- Full checkout.liquid access
- Can track all checkout steps
- Access to Liquid objects in checkout
- Can modify checkout DOM
Code Example - Plus Checkout Tracking:
{% if first_time_accessed %}
<script>
dataLayer.push({
event: 'checkout',
ecommerce: {
checkout: {
actionField: {step: 1},
products: [
{% for line_item in line_items %}
{
id: '{{ line_item.product_id }}',
name: '{{ line_item.title }}',
price: '{{ line_item.price | money_without_currency }}',
quantity: {{ line_item.quantity }}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
}
}
});
</script>
{% endif %}
Theme Compatibility and Liquid Variables
Different Shopify themes have varying implementations:
Dawn Theme (Shopify 2.0):
- Section-based architecture
- Uses
{{ content_for_header }}extensively - Supports app blocks
- JSON-based theme structure
Vintage Themes:
- Template-based structure
- May have outdated JavaScript
- Limited app block support
Accessing Product Data:
<script>
{% if product %}
window.productData = {
id: {{ product.id }},
title: {{ product.title | json }},
price: {{ product.price | money_without_currency }},
compareAtPrice: {{ product.compare_at_price | money_without_currency }},
vendor: {{ product.vendor | json }},
type: {{ product.type | json }},
tags: {{ product.tags | json }},
variants: {{ product.variants | json }}
};
{% endif %}
</script>
Accessing Cart Data:
<script>
window.cartData = {{ cart | json }};
console.log('Cart item count:', {{ cart.item_count }});
console.log('Cart total:', {{ cart.total_price | money_without_currency }});
</script>
App Conflicts
Shopify's app ecosystem can create tracking conflicts:
Common Conflict Scenarios:
- Multiple apps injecting Google Analytics (Facebook Channel, Google Channel, marketing apps)
- Pixel apps conflicting with native tracking
- Review apps modifying product page structure
- Currency converter apps changing prices
- Subscription apps modifying cart behavior
Diagnostic - Check Active Pixels:
// Shopify Web Pixels API
if (window.Shopify && window.Shopify.analytics) {
console.log('Shopify Analytics:', window.Shopify.analytics);
}
// Check for multiple GA instances
const scripts = Array.from(document.querySelectorAll('script'));
const trackingScripts = scripts.filter(s =>
s.src.includes('google-analytics.com') ||
s.src.includes('googletagmanager.com') ||
s.src.includes('facebook.net')
);
console.log('Found tracking scripts:', trackingScripts.length);
trackingScripts.forEach(s => console.log(s.src));
Customer Events (Web Pixels API)
Shopify's modern tracking approach using Customer Events:
Subscribe to Events:
// In Settings → Customer events → Add custom pixel
analytics.subscribe("page_viewed", (event) => {
console.log("Page viewed:", event);
// Your tracking code
});
analytics.subscribe("product_viewed", (event) => {
console.log("Product viewed:", event.data.productVariant);
});
analytics.subscribe("product_added_to_cart", (event) => {
console.log("Added to cart:", event.data.cartLine);
});
analytics.subscribe("checkout_started", (event) => {
console.log("Checkout started:", event.data.checkout);
});
analytics.subscribe("checkout_completed", (event) => {
console.log("Purchase:", event.data.checkout);
});
Advantages of Web Pixels:
- Works on all pages including checkout (even non-Plus)
- Loads in sandbox for better performance
- Doesn't conflict with theme code
- Survives theme changes
Comprehensive Diagnostic Checklist
1. Verify Code Injection Location
Check Theme Files:
# Look for tracking code in theme.liquid
# Admin → Online Store → Themes → Actions → Edit code
# Check these files:
# - layout/theme.liquid
# - snippets/google-analytics.liquid (if using snippet)
# - templates/product.liquid
Check Customer Events:
- Settings → Customer events
- Look for custom pixels
- Verify pixel status is "Active"
Validation Code:
<!-- Add to theme.liquid to verify code location -->
<script>
console.log('Theme.liquid loaded');
console.log('Template:', '{{ template }}');
console.log('Customer:', {{ customer | json }});
</script>
2. Inspect Shopify Objects
// Check all available Shopify objects
console.log('Shopify object:', window.Shopify);
console.log('Shop:', window.Shopify.shop);
console.log('Theme:', window.Shopify.theme);
console.log('Currency:', window.Shopify.currency);
// Check Analytics object
if (window.Shopify.analytics) {
console.log('Analytics meta:', window.Shopify.analytics.meta);
console.log('Replayqueue:', window.Shopify.analytics.replayQueue);
}
// Check for product
if (window.meta && window.meta.product) {
console.log('Product meta:', window.meta.product);
}
3. Monitor AJAX Cart Events
Shopify themes use AJAX for cart operations:
// Listen for AJAX cart events
document.addEventListener('DOMContentLoaded', function() {
// Override fetch for cart requests
const originalFetch = window.fetch;
window.fetch = function(...args) {
const url = args[0];
if (typeof url === 'string' && url.includes('/cart/')) {
console.log('Cart API call:', url);
}
return originalFetch.apply(this, args);
};
});
// For themes using XMLHttpRequest
const originalOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url) {
if (url.includes('/cart/')) {
console.log('XHR Cart call:', method, url);
}
return originalOpen.apply(this, arguments);
};
4. Check App Integrations
// Check for Facebook Pixel from multiple sources
console.log('Facebook Pixel:', window.fbq);
// Check for common Shopify app tracking
const appIndicators = [
'Shopify.cdnHost',
'BoostSDK', // Boost apps
'SECOMAPP', // SEO apps
'bsm', // Better Sales & Marketing
'Stamped', // Reviews app
'yotpo', // Reviews app
];
appIndicators.forEach(indicator => {
if (window[indicator]) {
console.log(`Found app indicator: ${indicator}`, window[indicator]);
}
});
5. Test Checkout Tracking
For Non-Plus Stores:
<!-- In Additional Scripts section -->
{% if first_time_accessed %}
<script>
// This runs only on order confirmation page
console.log('Order:', {{ order | json }});
dataLayer.push({
event: 'purchase',
ecommerce: {
transaction_id: '{{ order.order_number }}',
value: {{ order.total_price | money_without_currency }},
currency: '{{ shop.currency }}',
tax: {{ order.tax_price | money_without_currency }},
shipping: {{ order.shipping_price | money_without_currency }},
items: [
{% for line_item in order.line_items %}
{
item_id: '{{ line_item.product_id }}',
item_name: '{{ line_item.title }}',
price: {{ line_item.price | money_without_currency }},
quantity: {{ line_item.quantity }}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
}
});
</script>
{% endif %}
Browser DevTools Debugging Steps
Network Tab Analysis
1. Filter Tracking Requests:
Filter: /collect|/analytics|/batches|/tr?|/pixel
2. Inspect Shopify Analytics:
- Look for
monorail-edge.shopifysvc.comrequests - These are Shopify's internal analytics
- Check payload for customer privacy settings
3. Verify Third-Party Pixels:
- Google Analytics:
google-analytics.com/collect - Facebook:
facebook.com/tr - TikTok:
analytics.tiktok.com
Console Debugging
// Enable verbose logging for Shopify Analytics
if (window.Shopify && window.Shopify.analytics) {
window.Shopify.analytics.publish = new Proxy(
window.Shopify.analytics.publish,
{
apply: function(target, thisArg, args) {
console.log('Shopify Analytics publish:', args);
return target.apply(thisArg, args);
}
}
);
}
// Debug dataLayer
if (window.dataLayer) {
window.dataLayer.push = new Proxy(window.dataLayer.push, {
apply: function(target, thisArg, args) {
console.log('dataLayer push:', args);
return target.apply(thisArg, args);
}
});
}
Application Tab Storage
Check Customer Privacy Settings:
// Shopify stores customer privacy preferences
const privacySettings = document.cookie.match(/_tracking_consent=([^;]+)/);
if (privacySettings) {
console.log('Tracking consent:', decodeURIComponent(privacySettings[1]));
}
// Check for customer privacy banner
console.log('Privacy meta:', window.Shopify?.customerPrivacy);
Common Symptoms and Causes
| Symptom | Likely Cause | Solution |
|---|---|---|
| No tracking on checkout | Not using Shopify Plus | Use Additional Scripts or Web Pixels API |
| Duplicate purchase events | Multiple apps + manual code | Audit apps and consolidate tracking |
| Wrong product prices | Currency converter app | Track before conversion or use original price |
| Cart events missing | AJAX cart not tracked | Implement fetch/XHR interceptors |
| Tracking only on homepage | Code only in index.liquid | Move to theme.liquid |
| Customer ID not tracked | Customer not logged in | Check {{ customer.id }} availability |
| Missing checkout steps | Non-Plus plan | Upgrade to Plus or use server-side tracking |
| Consent blocking all tracking | Customer privacy banner | Implement Shopify Customer Privacy API |
| Events fire twice | Both theme code and Web Pixel | Remove duplicate implementation |
| Data not in Liquid format | Incorrect filter | Use ` |
Tag Manager Troubleshooting
Google Tag Manager on Shopify
Installation Location:
<!-- In theme.liquid, right after <head> -->
{{ content_for_header }}
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-XXXXXX');</script>
<!-- End Google Tag Manager -->
<!-- Immediately after <body> tag -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
Data Layer Implementation:
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
{% if customer %}
customerId: '{{ customer.id }}',
customerEmail: '{{ customer.email }}',
{% endif %}
pageType: '{{ request.page_type }}',
shopCurrency: '{{ shop.currency }}'
});
{% if template contains 'product' %}
dataLayer.push({
event: 'productDetail',
ecommerce: {
detail: {
products: [{
id: '{{ product.id }}',
name: {{ product.title | json }},
price: '{{ product.price | money_without_currency }}',
variant: '{{ product.selected_or_first_available_variant.id }}'
}]
}
}
});
{% endif %}
</script>
E-commerce Tracking Issues
Enhanced E-commerce Implementation
Product Impressions (Collection Pages):
{% if template contains 'collection' %}
<script>
dataLayer.push({
event: 'productImpressions',
ecommerce: {
currencyCode: '{{ shop.currency }}',
impressions: [
{% for product in collection.products %}
{
id: '{{ product.id }}',
name: {{ product.title | json }},
price: '{{ product.price | money_without_currency }}',
list: '{{ collection.title }}',
position: {{ forloop.index }}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
}
});
</script>
{% endif %}
Add to Cart Tracking:
// Using Shopify's AJAX API
document.querySelectorAll('form[action="/cart/add"]').forEach(form => {
form.addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
fetch('/cart/add.js', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
console.log('Added to cart:', data);
dataLayer.push({
event: 'addToCart',
ecommerce: {
add: {
products: [{
id: data.product_id,
name: data.product_title,
price: (data.price / 100).toFixed(2),
variant: data.variant_id,
quantity: data.quantity
}]
}
}
});
// Redirect to cart or show notification
window.location.href = '/cart';
});
});
});
Purchase Tracking (Order Status Page):
{% if first_time_accessed %}
<script>
dataLayer.push({
event: 'purchase',
ecommerce: {
purchase: {
actionField: {
id: '{{ order.order_number }}',
affiliation: '{{ shop.name }}',
revenue: '{{ order.total_price | money_without_currency }}',
tax: '{{ order.tax_price | money_without_currency }}',
shipping: '{{ order.shipping_price | money_without_currency }}',
coupon: '{{ order.discount_applications[0].title }}'
},
products: [
{% for line_item in order.line_items %}
{
id: '{{ line_item.product_id }}',
name: {{ line_item.title | json }},
price: '{{ line_item.price | money_without_currency }}',
variant: '{{ line_item.variant_id }}',
quantity: {{ line_item.quantity }},
sku: '{{ line_item.sku }}'
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
}
}
});
</script>
{% endif %}
Cookie and Consent Management
Shopify Customer Privacy API
Check Privacy Settings:
// Modern approach using Shopify's Customer Privacy API
if (window.Shopify && window.Shopify.customerPrivacy) {
const privacy = window.Shopify.customerPrivacy;
// Check current consent
privacy.currentVisitorConsent().then(consent => {
console.log('Current consent:', consent);
console.log('Analytics allowed:', consent.analytics);
console.log('Marketing allowed:', consent.marketing);
console.log('Preferences allowed:', consent.preferences);
console.log('Sale of data allowed:', consent.sale_of_data);
});
// Set consent
privacy.setTrackingConsent({
analytics: true,
marketing: false,
preferences: true,
sale_of_data: false
});
}
Conditional Tracking Based on Consent:
function initializeTracking() {
if (window.Shopify && window.Shopify.customerPrivacy) {
window.Shopify.customerPrivacy.currentVisitorConsent().then(consent => {
if (consent.analytics) {
// Load Google Analytics
loadGoogleAnalytics();
}
if (consent.marketing) {
// Load Facebook Pixel
loadFacebookPixel();
}
});
} else {
// Fallback if API not available
loadGoogleAnalytics();
}
}
document.addEventListener('DOMContentLoaded', initializeTracking);
Google Consent Mode Integration:
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
// Set default consent
gtag('consent', 'default', {
'ad_storage': 'denied',
'analytics_storage': 'denied',
'ad_user_data': 'denied',
'ad_personalization': 'denied'
});
// Update based on Shopify privacy settings
if (window.Shopify && window.Shopify.customerPrivacy) {
window.Shopify.customerPrivacy.currentVisitorConsent().then(consent => {
gtag('consent', 'update', {
'analytics_storage': consent.analytics ? 'granted' : 'denied',
'ad_storage': consent.marketing ? 'granted' : 'denied',
'ad_user_data': consent.marketing ? 'granted' : 'denied',
'ad_personalization': consent.marketing ? 'granted' : 'denied'
});
});
}
</script>
When to Contact Support
Contact Shopify Support When:
Platform-Level Issues:
- Theme code changes not saving
- Customer events not appearing in settings
- Checkout pages returning errors
- Apps not installing properly
Provide to Shopify:
- Store URL (.myshopify.com)
- Theme name and version
- Screenshots of code editor
- List of installed apps
- Specific page URLs with issues
Contact Analytics Vendor When:
- Events firing correctly but not in reports
- Data attribution errors
- Report discrepancies
- API integration issues
Provide to Vendor:
- Example tracking requests (from Network tab)
- Console logs showing event data
- Property/Account IDs
- Timeline of when issue started
Contact Theme Developer When:
- Custom theme missing Liquid objects
- Theme conflicts with tracking code
- Template modifications not working
- AJAX cart customizations needed
Provide to Developer:
- Theme name and purchase details
- Code changes attempted
- Desired tracking behavior
- Browser console errors
General Fixes
For universal tracking concepts, see the Global Tracking Issues Hub.