Shopify GA4 Event Tracking
Learn how to track Shopify-specific events in Google Analytics 4, including native data layer events, custom theme events, and checkout tracking.
Shopify Native Data Layer Events
Shopify provides a built-in data layer with several pre-configured events that fire automatically. These events use the window.dataLayer object.
Available Native Events
| Event Name | When It Fires | Available On |
|---|---|---|
page_viewed |
Every page load | All pages |
product_viewed |
Product detail page view | Product pages |
collection_viewed |
Collection page view | Collection pages |
search_submitted |
Search performed | Search results |
product_added_to_cart |
Item added to cart | All pages with cart |
product_removed_from_cart |
Item removed from cart | Cart page |
checkout_started |
Checkout begins | Checkout (Plus only) |
checkout_completed |
Order placed | Order confirmation |
Accessing Shopify Data Layer
The Shopify data layer is automatically available in window.dataLayer. Example structure:
window.dataLayer = [
{
event: 'page_viewed',
page: {
pageType: 'product',
resourceType: 'product',
resourceId: 1234567890
},
user: {
customerId: null, // or customer ID if logged in
customerEmail: null,
customerFirstName: null,
customerLastName: null
}
}
];
Mapping Shopify Events to GA4
Using Google Tag Manager (Recommended)
GTM can listen to Shopify's data layer events and translate them to GA4 events.
1. Create Data Layer Variables
In GTM, create variables to capture Shopify data:
Variable: Page Type
- Type: Data Layer Variable
- Data Layer Variable Name:
page.pageType - Name:
DLV - Page Type
Variable: Product ID
- Type: Data Layer Variable
- Data Layer Variable Name:
ecommerce.detail.products.0.id - Name:
DLV - Product ID
Variable: Product Name
- Type: Data Layer Variable
- Data Layer Variable Name:
ecommerce.detail.products.0.name - Name:
DLV - Product Name
2. Create Custom Event Triggers
Trigger: Product Viewed
- Type: Custom Event
- Event name:
product_viewed - Name:
CE - Product Viewed
Trigger: Add to Cart
- Type: Custom Event
- Event name:
product_added_to_cart - Name:
CE - Add to Cart
Trigger: Remove from Cart
- Type: Custom Event
- Event name:
product_removed_from_cart - Name:
CE - Remove from Cart
3. Create GA4 Event Tags
Tag: GA4 - View Item
- Type: Google Analytics: GA4 Event
- Configuration Tag:
\{\{GA4 Configuration Tag\}\} - Event Name:
view_item - Event Parameters:
currency:\{\{Currency\}\}(from Shopify data layer)value:\{\{Product Price\}\}items: Use custom JavaScript or data layer products array
- Trigger:
CE - Product Viewed
Tag: GA4 - Add to Cart
- Type: Google Analytics: GA4 Event
- Configuration Tag:
\{\{GA4 Configuration Tag\}\} - Event Name:
add_to_cart - Event Parameters:
currency:\{\{Currency\}\}value:\{\{Product Price\}\}items: Products array from data layer
- Trigger:
CE - Add to Cart
Using Manual Theme Code
If not using GTM, you can listen to Shopify events and send to GA4 directly.
Add this to your theme.liquid after the GA4 initialization:
<script>
// Listen for Shopify data layer events
(function() {
const originalPush = window.dataLayer.push;
window.dataLayer.push = function() {
const args = Array.prototype.slice.call(arguments);
const event = args[0];
// Call original push
originalPush.apply(window.dataLayer, args);
// Map Shopify events to GA4
if (!event || !event.event) return;
switch(event.event) {
case 'product_viewed':
handleProductViewed(event);
break;
case 'product_added_to_cart':
handleAddToCart(event);
break;
case 'product_removed_from_cart':
handleRemoveFromCart(event);
break;
}
};
function handleProductViewed(event) {
if (!event.ecommerce || !event.ecommerce.detail) return;
const product = event.ecommerce.detail.products[0];
gtag('event', 'view_item', {
currency: event.ecommerce.currencyCode || 'USD',
value: parseFloat(product.price),
items: [{
item_id: product.id,
item_name: product.name,
item_brand: product.brand || '',
item_category: product.category || '',
item_variant: product.variant || '',
price: parseFloat(product.price),
quantity: 1
}]
});
}
function handleAddToCart(event) {
if (!event.ecommerce || !event.ecommerce.add) return;
const products = event.ecommerce.add.products;
const items = products.map(p => ({
item_id: p.id,
item_name: p.name,
item_brand: p.brand || '',
item_category: p.category || '',
item_variant: p.variant || '',
price: parseFloat(p.price),
quantity: p.quantity
}));
const totalValue = products.reduce((sum, p) => {
return sum + (parseFloat(p.price) * p.quantity);
}, 0);
gtag('event', 'add_to_cart', {
currency: event.ecommerce.currencyCode || 'USD',
value: totalValue,
items: items
});
}
function handleRemoveFromCart(event) {
if (!event.ecommerce || !event.ecommerce.remove) return;
const products = event.ecommerce.remove.products;
const items = products.map(p => ({
item_id: p.id,
item_name: p.name,
price: parseFloat(p.price),
quantity: p.quantity
}));
gtag('event', 'remove_from_cart', {
currency: event.ecommerce.currencyCode || 'USD',
items: items
});
}
})();
</script>
Custom Shopify Events
Beyond native events, you can track custom interactions specific to your store.
Newsletter Signup
Track newsletter form submissions:
<!-- In your newsletter form section -->
<script>
document.querySelector('#newsletter-form').addEventListener('submit', function(e) {
gtag('event', 'newsletter_signup', {
method: 'footer_form',
location: '{{ template.name }}'
});
});
</script>
Wishlist/Favorites
Track when customers add products to wishlists:
// When wishlist button is clicked
gtag('event', 'add_to_wishlist', {
currency: '{{ cart.currency.iso_code }}',
value: {{ product.price | money_without_currency }},
items: [{
item_id: '{{ product.id }}',
item_name: '{{ product.title }}',
price: {{ product.price | money_without_currency }},
quantity: 1
}]
});
Size/Variant Selection
Track when customers select product variants:
// Add to your product page JavaScript
document.querySelectorAll('input[name="id"]').forEach(function(radio) {
radio.addEventListener('change', function() {
const variant = JSON.parse(this.getAttribute('data-variant'));
gtag('event', 'select_item', {
item_list_name: 'Product Variants',
items: [{
item_id: variant.id,
item_name: variant.title,
item_variant: variant.option1 // Size, Color, etc.
}]
});
});
});
Quick View Modal
Track quick view opens:
// When quick view is triggered
gtag('event', 'view_item', {
item_list_name: 'Quick View',
items: [{
item_id: productId,
item_name: productTitle
}]
});
Store Locator Interactions
Track store locator searches:
gtag('event', 'store_locator_search', {
search_term: searchQuery,
results_count: storesFound.length
});
Checkout Events (Shopify Plus Only)
Shopify Plus stores with access to checkout.liquid can track detailed checkout events.
Begin Checkout Event
Fire when checkout starts:
<!-- In checkout.liquid -->
{% if checkout.step == 'contact_information' %}
<script>
gtag('event', 'begin_checkout', {
currency: '{{ checkout.currency }}',
value: {{ checkout.total_price | money_without_currency }},
items: [
{% for line_item in checkout.line_items %}
{
item_id: '{{ line_item.product_id }}',
item_name: '{{ line_item.title }}',
item_variant: '{{ line_item.variant_title }}',
price: {{ line_item.final_price | money_without_currency }},
quantity: {{ line_item.quantity }}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
});
</script>
{% endif %}
Add Shipping Info
Track when customer completes shipping information:
{% if checkout.step == 'shipping_method' %}
<script>
gtag('event', 'add_shipping_info', {
currency: '{{ checkout.currency }}',
value: {{ checkout.total_price | money_without_currency }},
shipping_tier: '{{ checkout.shipping_method.title }}',
items: [
{% for line_item in checkout.line_items %}
{
item_id: '{{ line_item.product_id }}',
item_name: '{{ line_item.title }}',
quantity: {{ line_item.quantity }}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
});
</script>
{% endif %}
Add Payment Info
Track when customer reaches payment step:
{% if checkout.step == 'payment_method' %}
<script>
gtag('event', 'add_payment_info', {
currency: '{{ checkout.currency }}',
value: {{ checkout.total_price | money_without_currency }},
payment_type: 'credit_card', // or dynamically detect
items: [
{% for line_item in checkout.line_items %}
{
item_id: '{{ line_item.product_id }}',
item_name: '{{ line_item.title }}',
quantity: {{ line_item.quantity }}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
});
</script>
{% endif %}
Order Confirmation (All Stores)
All Shopify stores can track purchases on the order confirmation page.
Settings → Checkout → Order status page → Additional scripts:
<script>
gtag('event', 'purchase', {
transaction_id: '{{ order.order_number }}',
affiliation: '{{ shop.name }}',
value: {{ total_price | money_without_currency }},
currency: '{{ currency }}',
tax: {{ tax_price | money_without_currency }},
shipping: {{ shipping_price | money_without_currency }},
items: [
{% for line_item in line_items %}
{
item_id: '{{ line_item.sku }}',
item_name: '{{ line_item.title }}',
item_brand: '{{ line_item.vendor }}',
item_category: '{{ line_item.product.type }}',
item_variant: '{{ line_item.variant_title }}',
price: {{ line_item.final_price | money_without_currency }},
quantity: {{ line_item.quantity }}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
});
</script>
Testing & Debugging
1. Use GA4 DebugView
Enable debug mode in GTM Preview or add:
gtag('config', 'G-XXXXXXXXXX', {
'debug_mode': true
});
2. Check Browser Console
Monitor window.dataLayer in browser console:
// View all data layer pushes
console.log(window.dataLayer);
// Listen for new pushes
const originalPush = window.dataLayer.push;
window.dataLayer.push = function() {
console.log('Data Layer Push:', arguments[0]);
originalPush.apply(window.dataLayer, arguments);
};
3. Verify Event Parameters
In GA4 DebugView:
- Check event name matches GA4 recommended events
- Verify
itemsarray structure is correct - Confirm
currencyuses ISO 4217 codes (USD, EUR, GBP) - Check
valueis numeric without currency symbols
4. Test Full Funnel
- Product page → Verify
view_item - Add to cart → Verify
add_to_cart - View cart → Verify
view_cart(if implemented) - Begin checkout → Verify
begin_checkout - Complete purchase → Verify
purchase
Common Issues
Events Fire Multiple Times
Cause: Multiple implementations (native + manual + GTM) or duplicate event listeners.
Fix:
- Remove duplicate GA4 scripts
- Use GTM to manage all events from one place
- Check for duplicate event listeners in theme JavaScript
Missing Product Data
Cause: Shopify data layer structure varies by theme and page type.
Fix:
- Log
window.dataLayerto console to inspect structure - Adjust variable paths in GTM to match your theme's structure
- Use fallback values for missing data
Checkout Events Don't Fire
Cause: Non-Plus store or incorrect checkout step detection.
Fix:
- Verify you have Shopify Plus
- Check
checkout.stepvalue matches your conditions - Test in actual checkout (not preview mode)
Next Steps
- GA4 Ecommerce Tracking - Complete ecommerce implementation
- Shopify Data Layer - Full data layer reference
- Events Not Firing - Troubleshooting guide
For general event tracking concepts, see GA4 Event Tracking Guide.