Google Analytics 4 Ecommerce Tracking on HubSpot
If you're using HubSpot Payments, HubSpot Commerce features, or selling products through HubSpot, this guide will help you implement GA4 ecommerce tracking.
Prerequisites
- Install GA4 on HubSpot
- Have HubSpot Payments or Commerce Hub enabled
- Access to HubSpot Site Header HTML or template code
HubSpot Ecommerce Capabilities
What HubSpot Offers for Ecommerce
HubSpot Payments:
- Process one-time and recurring payments
- Payment links and forms
- Quote-to-payment workflows
- Integrated with CRM deals
HubSpot Commerce Hub (Enterprise):
- Product catalog
- Shopping cart functionality
- Order management
- Invoicing and subscriptions
Third-Party Integrations:
- Shopify integration (syncs orders to HubSpot CRM)
- WooCommerce integration
- Custom integrations via API
GA4 Ecommerce Events for HubSpot
Recommended Events to Track
| Event | When to Fire | HubSpot Context |
|---|---|---|
view_item |
Product page viewed | HubSpot product catalog page |
add_to_cart |
Item added to cart | HubSpot cart interactions |
begin_checkout |
Checkout initiated | Payment form loaded |
add_payment_info |
Payment method added | Payment details entered |
purchase |
Transaction completed | Payment confirmation page |
Tracking Product Views
Track when visitors view products in your HubSpot product catalog.
Product View Tracking
Add to product template or use HubL in product pages:
<script>
// Track product view
gtag('event', 'view_item', {
'currency': '{{ product.currency }}',
'value': {{ product.price }},
'items': [{
'item_id': '{{ product.id }}',
'item_name': '{{ product.name }}',
'item_category': '{{ product.category }}',
'price': {{ product.price }},
'quantity': 1
}]
});
</script>
With HubL Variables
If using HubSpot product properties:
{% if content.product_id %}
<script>
gtag('event', 'view_item', {
'currency': 'USD',
'value': {{ content.product_price|default(0) }},
'items': [{
'item_id': '{{ content.product_id }}',
'item_name': '{{ content.product_name }}',
'item_category': '{{ content.product_category }}',
'price': {{ content.product_price|default(0) }},
'quantity': 1
}]
});
</script>
{% endif %}
Tracking Add to Cart
Track when items are added to a shopping cart or payment form.
HubSpot Payment Link Clicks
For HubSpot payment links and buttons:
<script>
document.addEventListener('click', function(event) {
var paymentLink = event.target.closest('a[href*="payments.hubspot.com"], .hs-payment-link');
if (paymentLink) {
var productName = paymentLink.getAttribute('data-product-name') || paymentLink.textContent.trim();
var productPrice = paymentLink.getAttribute('data-product-price') || '';
gtag('event', 'add_to_cart', {
'currency': 'USD',
'value': parseFloat(productPrice) || 0,
'items': [{
'item_name': productName,
'price': parseFloat(productPrice) || 0,
'quantity': 1
}]
});
}
});
</script>
Custom Add to Cart Buttons
If you've built custom cart functionality:
<button class="add-to-cart-btn"
data-product-id="PROD-123"
data-product-name="Premium Package"
data-product-price="99.00">
Add to Cart
</button>
<script>
document.addEventListener('click', function(event) {
if (event.target.classList.contains('add-to-cart-btn')) {
var productId = event.target.getAttribute('data-product-id');
var productName = event.target.getAttribute('data-product-name');
var productPrice = event.target.getAttribute('data-product-price');
gtag('event', 'add_to_cart', {
'currency': 'USD',
'value': parseFloat(productPrice),
'items': [{
'item_id': productId,
'item_name': productName,
'price': parseFloat(productPrice),
'quantity': 1
}]
});
}
});
</script>
Tracking Checkout Process
Begin Checkout Event
Fire when payment form is loaded:
<script>
// Check if on payment/checkout page
if (window.location.href.includes('payment') || window.location.href.includes('checkout')) {
gtag('event', 'begin_checkout', {
'currency': 'USD',
'value': {{ total_amount }},
'items': [{
'item_name': '{{ product_name }}',
'price': {{ product_price }},
'quantity': 1
}]
});
}
</script>
Add Payment Info Event
Fire when payment method is entered:
<script>
// Listen for payment form interactions
var paymentForm = document.querySelector('form[action*="payment"], .hs-payment-form');
if (paymentForm) {
var paymentFields = paymentForm.querySelectorAll('input[name*="card"], input[name*="payment"]');
paymentFields.forEach(function(field) {
field.addEventListener('blur', function() {
if (field.value.length > 0 && !window.paymentInfoTracked) {
window.paymentInfoTracked = true;
gtag('event', 'add_payment_info', {
'currency': 'USD',
'value': {{ payment_amount }},
'payment_type': 'credit_card'
});
}
});
});
}
</script>
Tracking Purchases (Conversions)
Track completed purchases on the payment confirmation page.
HubSpot Payment Confirmation Page
Add to your payment confirmation template:
<script>
// Track purchase on confirmation page
gtag('event', 'purchase', {
'transaction_id': '{{ payment.transaction_id }}',
'value': {{ payment.amount }},
'currency': '{{ payment.currency }}',
'tax': {{ payment.tax|default(0) }},
'items': [{
'item_id': '{{ payment.product_id }}',
'item_name': '{{ payment.product_name }}',
'price': {{ payment.product_price }},
'quantity': {{ payment.quantity|default(1) }}
}]
});
</script>
Using HubSpot Workflows API Data
If payment data is available via HubSpot's API:
{% if content.payment_confirmed %}
<script>
gtag('event', 'purchase', {
'transaction_id': '{{ contact.recent_deal_id }}',
'value': {{ contact.recent_deal_amount }},
'currency': 'USD',
'items': [{
'item_id': '{{ content.product_id }}',
'item_name': '{{ content.product_name }}',
'price': {{ content.product_price }},
'quantity': 1
}]
});
</script>
{% endif %}
Prevent Duplicate Purchase Events
Ensure purchase event only fires once:
<script>
// Check if purchase already tracked (use session storage)
var transactionId = '{{ payment.transaction_id }}';
if (transactionId && !sessionStorage.getItem('tracked_' + transactionId)) {
gtag('event', 'purchase', {
'transaction_id': transactionId,
'value': {{ payment.amount }},
'currency': 'USD',
'items': [{
'item_name': '{{ payment.product_name }}',
'price': {{ payment.product_price }},
'quantity': 1
}]
});
// Mark as tracked
sessionStorage.setItem('tracked_' + transactionId, 'true');
}
</script>
Tracking HubSpot-Shopify Integration
If you've integrated Shopify with HubSpot, track both platforms separately.
Strategy for HubSpot-Shopify
Track in Shopify:
- Full ecommerce funnel (view_item, add_to_cart, purchase)
- Use Shopify's native GA4 integration
- See Shopify GA4 Setup
Track in HubSpot:
- Post-purchase engagement (emails, content downloads)
- CRM interactions (meetings, form submissions)
- Customer lifecycle progression
Link the Data: Use the same GA4 property for both:
- Implement User ID tracking with HubSpot contact ID
- Use cross-domain tracking if needed
- Match customer emails between systems
Tracking Subscription/Recurring Payments
For HubSpot recurring payment tracking:
Initial Subscription Purchase
<script>
gtag('event', 'purchase', {
'transaction_id': '{{ subscription.initial_transaction_id }}',
'value': {{ subscription.amount }},
'currency': 'USD',
'items': [{
'item_id': '{{ subscription.plan_id }}',
'item_name': '{{ subscription.plan_name }}',
'item_category': 'subscription',
'price': {{ subscription.amount }},
'quantity': 1
}]
});
</script>
Subscription Renewals
Track recurring charges (requires workflow or API integration):
<script>
// Track renewal (trigger via webhook or workflow)
gtag('event', 'purchase', {
'transaction_id': '{{ renewal.transaction_id }}',
'value': {{ renewal.amount }},
'currency': 'USD',
'items': [{
'item_id': '{{ renewal.plan_id }}',
'item_name': '{{ renewal.plan_name }}',
'item_category': 'subscription_renewal',
'price': {{ renewal.amount }},
'quantity': 1
}]
});
</script>
Enhanced Ecommerce with CRM Data
Leverage HubSpot CRM data for richer ecommerce insights.
Track Customer Lifetime Value
<script>
{% if contact %}
gtag('set', 'user_properties', {
'customer_ltv': '{{ contact.total_revenue }}',
'lifecycle_stage': '{{ contact.lifecycle_stage }}',
'customer_since': '{{ contact.createdate }}',
'total_purchases': {{ contact.num_associated_deals|default(0) }}
});
{% endif %}
</script>
Track Deal Stage Progression
<script>
// Track when deals move to specific stages
window.addEventListener('message', function(event) {
if (event.data.type === 'hubspot_deal_update') {
var dealStage = event.data.dealStage;
if (dealStage === 'closedwon') {
gtag('event', 'purchase', {
'transaction_id': event.data.dealId,
'value': event.data.dealAmount,
'currency': 'USD'
});
}
}
});
</script>
GTM Implementation for Ecommerce
For complex ecommerce setups, use Google Tag Manager.
Create Data Layer for Products
In product templates:
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'event': 'view_item',
'ecommerce': {
'currency': 'USD',
'value': {{ product.price }},
'items': [{
'item_id': '{{ product.id }}',
'item_name': '{{ product.name }}',
'item_category': '{{ product.category }}',
'price': {{ product.price }},
'quantity': 1
}]
}
});
</script>
Create GTM Triggers
Product View Trigger:
- Type: Custom Event
- Event: view_item
Purchase Trigger:
- Type: Custom Event
- Event: purchase
See GTM Data Layer Guide for complete implementation.
Testing Ecommerce Tracking
1. Use GA4 DebugView
- Enable debug mode in GA4 config
- Go through purchase funnel
- Verify events fire in correct order:
- view_item
- add_to_cart
- begin_checkout
- add_payment_info
- purchase
2. Check Ecommerce Reports
After 24-48 hours:
- GA4 → Reports → Monetization → Ecommerce purchases
- Verify transactions appear
- Check revenue amounts match
3. Test Purchase Event Parameters
Use browser DevTools:
// Check data layer (if using GTM)
console.log(dataLayer);
// Check most recent purchase event
dataLayer.filter(item => item.event === 'purchase');
4. Verify Transaction IDs Are Unique
- Each purchase should have unique transaction_id
- Prevents duplicate revenue counting
- Test by refreshing confirmation page (shouldn't fire again)
Troubleshooting
Duplicate Purchase Events
Problem: Purchase event fires multiple times
Solutions:
- Use sessionStorage to track fired events
- Ensure code only on confirmation page, not thank you page
- Check for multiple GA4 implementations
Fix:
var txnId = '{{ transaction_id }}';
if (!sessionStorage.getItem('purchase_' + txnId)) {
gtag('event', 'purchase', {...});
sessionStorage.setItem('purchase_' + txnId, '1');
}
Missing Revenue Data
Problem: Events fire but no revenue in reports
Causes:
- Missing
valueparameter valueset to 0 or null- Wrong currency format
- Items array malformed
Verify:
// Ensure value is a number, not string
'value': parseFloat('{{ amount }}') || 0
HubL Variables Not Available
Problem: Product data not accessible in templates
Solutions:
- Verify you're on a product/payment page
- Check HubSpot product catalog is configured
- Use HubSpot's product object structure
- Test with static data first
Ecommerce Events Not Showing in GA4
Check:
- GA4 base configuration is working
- Ecommerce measurement is enabled in GA4 (Admin → Data Settings)
- Event syntax matches GA4 spec exactly
- Items array is properly formatted
- No ad blockers during testing
Advanced: Server-Side Ecommerce Tracking
For more accurate tracking, consider server-side implementation.
Using HubSpot Workflows
Create workflow that sends purchase data to GA4 Measurement Protocol:
- Trigger: Deal stage changes to "Closed Won"
- Action: Webhook to GA4 Measurement Protocol
- Endpoint:
https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXXXXX&api_secret=YOUR_SECRET - Payload:
{
"client_id": "{{ contact.vid }}",
"events": [{
"name": "purchase",
"params": {
"transaction_id": "{{ deal.id }}",
"value": {{ deal.amount }},
"currency": "USD",
"items": [{
"item_name": "{{ deal.dealname }}",
"price": {{ deal.amount }}
}]
}
}]
}
See GA4 Measurement Protocol documentation for details.
Next Steps
- Install GTM - For easier ecommerce tracking
- Configure GTM Data Layer - Pass product data to GTM
- Troubleshoot Events - Debug tracking issues
For general GA4 ecommerce concepts, see GA4 Ecommerce Guide.