This is the documentation you will need if you wish to do custom set ups on your 3rd party analytics.
# Consent API & Event Documentation
Technical Reference for Developers & Agencies
This document provides detailed technical information about the events we track and the Consent API implementation. For general merchant information, see the [Analytics & Tracking Documentation](merchant-analytics-documentation.md).
---
## Table of Contents
1. [GTM Template Download](#gtm-template-download)
2. [Event Reference](#event-reference)
3. [Consent API](#consent-api)
4. [Testing & Debugging](#testing--debugging)
5. [Multi-Currency Support](#multi-currency-support)
---
## GTM Template Download
For Store-Only Mode users: Download our pre-configured GTM container template with all tracking tags, triggers, and variables.
Download: [enjovia-platform-gtm-template.json](https://res.cloudinary.com/enjovia/raw/upload/v1760990872/GTM/enjovia-platform-gtm-template.json)
What's included:
- ✅ 6 Tags (GA4 Config, GA4 Events, Meta Base, Meta Events, TikTok Base, TikTok Events)
- ✅ 6 Triggers (conditional on pixel IDs)
- ✅ 11 Variables (all read from dataLayer)
- ✅ Zero hardcoded dependencies - fully portable
Import instructions: Use Admin → Import Container in Google Tag Manager. [Learn more](https://support.google.com/tagmanager/answer/6106997)
---
## Event Reference
All events are pushed to window.dataLayer and follow GA4 ecommerce event standards.
### Event: analytics_config
When: Page load (first event, fires once per session)
Purpose: Initialize tracking pixels with store configuration
```javascript
{
event: 'analytics_config',
store_analytics: {
ga4_measurement_id: 'G-XXXXXXXXXX', // null if not configured
meta_pixel_id: '1234567890', // null if not configured
tiktok_pixel_id: 'ABCDEFG1234567', // null if not configured
consent_required: true // boolean
},
store_context: {
store_id: 'store_abc123',
store_name: 'Your Store Name',
store_domain: 'yourstore.com',
store_locale: 'en_GB',
is_live: true, // False for test orders
}
}
```
Use in GTM: Trigger pixel initialization tags (GA4 Config, Meta Base Code, TikTok Base Code)
---
### Event: view_item_list
When: Homepage or category page load
Purpose: Track product discovery and browsing behavior
```javascript
{
event: 'view_item_list',
ecommerce: {
currency: 'GBP', // Event-level currency
item_list_id: 'homepage', // or category ID (e.g., 'cat_123')
item_list_name: 'All Products', // or category name
items: [
{
item_id: 'prod_123',
item_name: 'Spa Day Experience',
item_category: 'Experience', // Present if from category page
price: 50.00,
discount: 10.00, // If on sale (optional)
index: 0, // Position in list (0-indexed)
quantity: 1
},
{
item_id: 'prod_456',
item_name: 'Afternoon Tea',
item_category: 'Experience',
price: 35.00,
index: 1,
quantity: 1
}
// ... more products
]
}
}
```
GA4 Mapping: view_item_list
Meta/TikTok: Not sent (use view_item for individual product views)
---
### Event: view_item
When: Product detail page view
Purpose: Track product interest
```javascript
{
event: 'view_item',
ecommerce: {
currency: 'GBP',
value: 50.00, // Base product price
items: [
// Main product only
{
item_id: 'prod_123',
item_name: 'Spa Day Experience',
affiliation: 'Your Store Name', // Store name
item_brand: 'Your Store Name', // Store name
item_category: 'Experience', // If from category (optional)
item_list_id: 'cat_456', // If from category (optional)
item_list_name: 'Experiences', // If from category (optional)
price: 50.00,
quantity: 1,
discount: 10.00 // If on sale (optional)
}
]
}
}
```
Note: Available enhancements are tracked separately via a view_item_list event with item_list_name = "Product Name - Available Enhancements"
GA4 Mapping: view_item (main product only)
Meta Mapping: ViewContent
TikTok Mapping: ViewContent
---
### Event: add_to_cart
When: Product successfully added to basket (after shipping selected)
Purpose: Track conversion funnel entry
```javascript
{
event: 'add_to_cart',
ecommerce: {
currency: 'GBP',
value: 115.99, // Product + selected enhancements + shipping
items: [
// Main product
{
item_id: 'prod_123',
item_name: 'Spa Day Experience',
item_category: 'Experience', // If from category (optional)
item_variant: 'Deluxe', // If variant product (optional)
price: 50.00,
quantity: 1
},
// Selected enhancement - multiple quantity
{
item_id: 'addon_456',
item_name: 'Champagne Upgrade',
item_category: 'Enhancement',
price: 25.00,
quantity: 2, // Customer selected 2
item_list_id: 'prod_123',
item_list_name: 'Spa Day Experience'
},
// Selected enhancement - single quantity
{
item_id: 'addon_789',
item_name: 'Lunch Included',
item_category: 'Enhancement',
price: 30.00,
quantity: 1, // Customer selected 1
item_list_id: 'prod_123',
item_list_name: 'Spa Day Experience'
},
// Shipping method
{
item_id: 'del_123',
item_name: 'Royal Mail 1st Class',
item_category: 'Shipping',
price: 10.99,
quantity: 1
}
]
}
}
```
GA4 Mapping: add_to_cart (all items: product, enhancements, shipping)
Meta Mapping: AddToCart (product only, value includes total)
TikTok Mapping: AddToCart (product only, value includes total)
Note: Monetary products append value to name (e.g., "Gift Card - £50.00")
---
### Event: remove_from_cart
When: Item removed from checkout page
Purpose: Track cart abandonment signals
```javascript
{
event: 'remove_from_cart',
ecommerce: {
currency: 'GBP',
value: 75.99, // Value of removed items
items: [
// Main product
{
item_id: 'prod_123',
item_name: 'Spa Day Experience',
affiliation: 'Your Store Name',
item_brand: 'Your Store Name',
item_category: 'Experience', // If from category (optional)
item_variant: 'Deluxe', // If variant product (optional)
price: 50.00,
quantity: 1,
discount: 5.00, // If promotion active (optional)
promotion_id: 'promo_123', // If promotion active (optional)
promotion_name: 'Summer Sale' // If promotion active (optional)
},
// Enhancements
{
item_id: 'addon_456',
item_name: 'Champagne Upgrade',
affiliation: 'Your Store Name',
item_brand: 'Your Store Name',
item_category: 'Enhancement',
price: 15.00,
quantity: 1,
item_list_id: 'prod_123',
item_list_name: 'Spa Day Experience',
discount: 2.00, // If promotion active (optional)
promotion_id: 'promo_123', // If promotion active (optional)
promotion_name: 'Summer Sale' // If promotion active (optional)
},
// Shipping
{
item_id: 'del_123',
item_name: 'Royal Mail 1st Class',
affiliation: 'Your Store Name',
item_brand: 'Your Store Name',
item_category: 'Shipping',
price: 10.99,
quantity: 1,
discount: 0.00, // If promotion active (optional)
promotion_id: 'promo_123', // If promotion active (optional)
promotion_name: 'Summer Sale' // If promotion active (optional)
}
]
}
}
```
GA4 Mapping: remove_from_cart
Meta Mapping: RemoveFromCart (custom event)
TikTok Mapping: CustomEvent: RemoveFromCart
---
### Event: view_cart
When: Checkout page load
Purpose: Track cart analysis and abandonment funnel entry
```javascript
{
event: 'view_cart',
ecommerce: {
currency: 'GBP',
value: 150.98, // Total cart value
coupon: 'SUMMER10', // If promotion active (optional)
items: [
// All basket items (products + enhancements + shipping)
{
item_id: 'prod_123',
item_name: 'Spa Day Experience',
item_category: 'Experience', // If from category (optional)
item_variant: 'Deluxe', // If variant product (optional)
price: 50.00,
quantity: 1,
discount: 5.00, // If promotion active (optional)
promotion_id: 'promo_123', // If promotion active (optional)
promotion_name: 'Summer Sale' // If promotion active (optional)
},
{
item_id: 'addon_456',
item_name: 'Champagne Upgrade',
item_category: 'Enhancement',
price: 15.00,
quantity: 1,
item_list_id: 'prod_123',
item_list_name: 'Spa Day Experience',
discount: 2.00, // If promotion active (optional)
promotion_id: 'promo_123', // If promotion active (optional)
promotion_name: 'Summer Sale' // If promotion active (optional)
},
// ... more items
]
}
}
```
Smart Reload Protection: Only fires once per session to prevent duplicate tracking on browser back/forward navigation
GA4 Mapping: view_cart
Meta Mapping: ViewCart (custom event)
TikTok Mapping: CustomEvent: ViewCart
---
### Event: begin_checkout
When: "Proceed to Payment" button clicked
Purpose: Track high-intent purchase signals
```javascript
{
event: 'begin_checkout',
ecommerce: {
currency: 'GBP',
value: 140.98, // After discount applied
coupon: 'SUMMER10', // If discount code applied (optional)
items: [
{
item_id: 'prod_123',
item_name: 'Spa Day Experience',
item_category: 'Experience', // If from category (optional)
item_variant: 'Deluxe', // If variant product (optional)
price: 50.00, // Discounted price (what customer pays)
quantity: 1,
discount: 5.00, // If promotion active (optional)
promotion_id: 'promo_123', // If promotion active (optional)
promotion_name: 'Summer Sale' // If promotion active (optional)
},
{
item_id: 'addon_456',
item_name: 'Champagne Upgrade',
item_category: 'Enhancement',
price: 15.00,
quantity: 1,
item_list_id: 'prod_123',
item_list_name: 'Spa Day Experience',
discount: 2.00, // If promotion active (optional)
promotion_id: 'promo_123', // If promotion active (optional)
promotion_name: 'Summer Sale' // If promotion active (optional)
},
// ... shipping, etc.
]
}
}
```
GA4 Mapping: begin_checkout
Meta Mapping: InitiateCheckout
TikTok Mapping: InitiateCheckout
---
### Event: purchase
When: Order confirmation page load
Purpose: Track revenue and conversion
```javascript
{
event: 'purchase',
ecommerce: {
transaction_id: 'ORD-12345', // Unique order reference
currency: 'GBP',
value: 140.98, // Total revenue (after discount, including tax)
tax: 23.50, // Tax amount
coupon: 'SUMMER10', // If applied (optional)
items: [
// All purchased items (products, enhancements, shipping)
{
item_id: 'prod_123',
item_name: 'Spa Day Experience',
item_category: 'Experience', // If from category (optional)
item_variant: 'Deluxe', // If variant product (optional)
price: 50.00, // Discounted price (what customer pays)
quantity: 1,
discount: 5.00, // If promotion active (optional)
promotion_id: 'promo_123', // If promotion active (optional)
promotion_name: 'Summer Sale' // If promotion active (optional)
},
{
item_id: 'addon_456',
item_name: 'Champagne Upgrade',
item_category: 'Enhancement',
price: 15.00,
quantity: 1,
discount: 2.00, // If promotion active (optional)
promotion_id: 'promo_123', // If promotion active (optional)
promotion_name: 'Summer Sale' // If promotion active (optional)
},
// ... shipping, etc.
]
}
}
```
One-Time Protection: Only fires once per order to prevent revenue duplication on page reloads
GA4 Mapping: purchase
Meta Mapping: Purchase
TikTok Mapping: CompletePayment
---
### Event: view_promotion
When: Available discount displayed on checkout page
Purpose: Track promotion visibility
```javascript
{
event: 'view_promotion',
ecommerce: {
creative_name: 'Promotion Banner', // Display type
creative_slot: 'checkout_banner', // Location on page
promotion_id: 'promo_789', // Unique promotion ID
promotion_name: '10% Summer Sale', // Promotion title
location_id: 'checkout' // Page context
}
}
```
Note: Promotion events do NOT include items, currency, or value - they track promotion visibility and selection only.
GA4 Mapping: view_promotion
Meta/TikTok: Not sent
---
### Event: select_promotion
When: Discount code applied or auto-selected
Purpose: Track promotion engagement and conversion
```javascript
{
event: 'select_promotion',
ecommerce: {
creative_name: 'Code Entry', // How promotion was selected
creative_slot: 'checkout_code_entry', // Input location (or 'auto_applied')
promotion_id: 'promo_789', // Unique promotion ID
promotion_name: '10% Summer Sale', // Promotion title
location_id: 'checkout' // Page context
}
}
```
Note: Promotion events do NOT include items, currency, or value. To analyze promotion impact on revenue, correlate select_promotion with subsequent purchase events using the coupon parameter in the purchase event.
GA4 Mapping: select_promotion
Meta/TikTok: Not sent
---
## Consent API
We implement Google Consent Mode v2 which initializes BEFORE any tracking scripts load.
### Consent Types
Four consent categories are managed:
| Type | Purpose | Default (consent required) | Default (no consent) |
|------|---------|---------------------------|---------------------|
| analytics_storage | Analytics cookies (GA4) | denied | granted |
| ad_storage | Advertising cookies | denied | granted |
| ad_user_data | User data for ads | denied | granted |
| ad_personalization | Ad personalization | denied | granted |
### Initialization
Consent Mode v2 is initialized before GTM loads:
```javascript
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
// If consent_required: true
gtag('consent', 'default', {
'analytics_storage': 'denied',
'ad_storage': 'denied',
'ad_user_data': 'denied',
'ad_personalization': 'denied',
'wait_for_update': 500 // Wait 500ms for stored consent
});
// If consent_required: false
gtag('consent', 'default', {
'analytics_storage': 'granted',
'ad_storage': 'granted',
'ad_user_data': 'granted',
'ad_personalization': 'granted'
});
```
### User Consent Update
When user accepts cookies via the banner:
```javascript
gtag('consent', 'update', {
'analytics_storage': 'granted',
'ad_storage': 'granted',
'ad_user_data': 'granted',
'ad_personalization': 'granted'
});
```
### Consent Storage
User consent is stored in localStorage for 365 days:
```javascript
localStorage.getItem('enjovia_consent')
// Returns:
{
"analytics_storage": "granted",
"ad_storage": "granted",
"ad_user_data": "granted",
"ad_personalization": "granted",
"timestamp": 1729449600000, // Expires after 365 days
"version": 1
}
```
### Checking Consent Programmatically
```javascript
// Check if user has made a consent choice
const consentData = JSON.parse(localStorage.getItem('enjovia_consent') || 'null');
if (consentData) {
console.log('Consent granted:', consentData.analytics_storage === 'granted');
console.log('Expires:', new Date(consentData.timestamp + 365 24 60 60 1000));
} else {
console.log('No consent choice stored');
}
```
### Updating Consent in Store-Only Mode
If you're managing consent yourself, update it before your GTM container loads:
```javascript
// Initialize with denied
gtag('consent', 'default', {
'analytics_storage': 'denied',
'ad_storage': 'denied',
'ad_user_data': 'denied',
'ad_personalization': 'denied'
});
// Update when user accepts (from your own consent banner)
function handleUserAcceptsCookies() {
gtag('consent', 'update', {
'analytics_storage': 'granted',
'ad_storage': 'granted',
'ad_user_data': 'granted',
'ad_personalization': 'granted'
});
// Store choice
localStorage.setItem('enjovia_consent', JSON.stringify({
analytics_storage: 'granted',
ad_storage: 'granted',
ad_user_data: 'granted',
ad_personalization: 'granted',
timestamp: Date.now(),
version: 1
}));
}
```
---
## Item Filtering (Meta & TikTok)
Platform automatically filters items for Meta and TikTok pixels:
Included:
- Main products (item_category != 'Enhancement' and != 'Shipping')
Excluded:
- Enhancement (item_category === 'Enhancement')
- Shipping (item_category === 'Shipping')
Value calculation:
- Total value includes all items (products + enhancements + shipping)
- Only products appear in contents array for Meta/TikTok
Example:
```javascript
// dataLayer event
{
event: 'add_to_cart',
ecommerce: {
value: 75.99, // Product (50) + Enhancement (15) + Shipping (10.99)
items: [
{ item_id: 'prod_123', price: 50.00, item_category: null },
{ item_id: 'addon_456', price: 15.00, item_category: 'Enhancement' },
{ item_id: 'del_royal', price: 10.99, item_category: 'Shipping' }
]
}
}
// What Meta/TikTok receive
{
value: 75.99, // Full value
contents: [
{ id: 'prod_123', quantity: 1, item_price: 50.00 } // Only product
]
}
```
---
## Best Practices for Developers
### GTM Variable Setup
Use dataLayer variables in GTM:
```javascript
// GA4 Measurement ID
{{DLV - ga4_measurement_id}} // store_analytics.ga4_measurement_id
// Meta Pixel ID
{{DLV - meta_pixel_id}} // store_analytics.meta_pixel_id
// TikTok Pixel ID
{{DLV - tiktok_pixel_id}} // store_analytics.tiktok_pixel_id
// Ecommerce data
{{DLV - ecommerce}} // ecommerce object
{{DLV - ecommerce.items}} // items array
{{DLV - ecommerce.value}} // transaction value
{{DLV - ecommerce.currency}} // currency code
```
### Conditional Triggers
Only fire tags when IDs are present:
```javascript
// Trigger condition for GA4 tags
{{DLV - ga4_measurement_id}} does not equal undefined
// Trigger condition for Meta tags
{{DLV - meta_pixel_id}} does not equal undefined
// Trigger condition for TikTok tags
{{DLV - tiktok_pixel_id}} does not equal undefined
```
### Event Naming
Match exact event names in GTM triggers:
- Custom Event: analytics_config
- Custom Event: view_item_list
- Custom Event: view_item
- Custom Event: add_to_cart
- Custom Event: remove_from_cart
- Custom Event: view_cart
- Custom Event: begin_checkout
- Custom Event: purchase
- Custom Event: view_promotion
- Custom Event: select_promotion