Ecwid automatically pushes ecommerce events to the data layer using the Ecwid JavaScript API. This guide provides complete reference for all available data layer events and how to use them in Google Tag Manager.
Data Layer Overview
Ecwid uses a custom data layer structure based on the Ecwid JavaScript API. Unlike Shopify's native data layer, Ecwid requires manual data layer implementation using the API.
How Ecwid Data Layer Works
- Ecwid API loads → JavaScript API becomes available
- User interactions → API callbacks trigger
- Data layer pushes → Events pushed to
window.dataLayer - GTM captures → Triggers fire based on events
- Tags execute → Send data to analytics platforms
Data Layer Implementation
Ecwid doesn't push to data layer by default. You must implement it using the Ecwid API.
Implementing Ecwid Data Layer
Add this code to Ecwid Control Panel → Settings → General → Tracking & Analytics → Custom JavaScript Code.
Complete Data Layer Implementation
<script>
// Initialize data layer
window.dataLayer = window.dataLayer || [];
// Wait for Ecwid API
Ecwid.OnAPILoaded.add(function() {
console.log('Ecwid Data Layer Initialized');
// Push initial page load
dataLayer.push({
'event': 'ecwid_loaded',
'ecwid_store_id': Ecwid.getStorefrontInfo().storeId
});
// Product Viewed
Ecwid.OnPageLoad.add(function(page) {
if (page.type === 'PRODUCT') {
Ecwid.getProduct(page.productId, function(product) {
dataLayer.push({
'event': 'product_viewed',
'ecommerce': {
'currencyCode': product.currency || 'USD',
'detail': {
'products': [{
'id': product.id.toString(),
'name': product.name,
'price': product.defaultDisplayedPrice,
'brand': product.brand || '',
'category': getCategoryName(product.categoryIds),
'variant': product.sku || '',
'dimension1': product.inStock ? 'In Stock' : 'Out of Stock'
}]
}
},
'product': {
'id': product.id,
'name': product.name,
'price': product.defaultDisplayedPrice,
'currency': product.currency || 'USD',
'inStock': product.inStock,
'url': product.url
}
});
});
}
// Category Viewed
if (page.type === 'CATEGORY') {
dataLayer.push({
'event': 'category_viewed',
'category': {
'id': page.categoryId,
'name': 'Category ' + page.categoryId
}
});
}
// Search Performed
if (page.type === 'SEARCH') {
dataLayer.push({
'event': 'search_performed',
'search': {
'term': page.keywords
}
});
}
// Checkout Started
if (page.type === 'CHECKOUT_ADDRESS') {
Ecwid.Cart.get(function(cart) {
dataLayer.push({
'event': 'checkout_started',
'ecommerce': {
'currencyCode': cart.currency || 'USD',
'checkout': {
'actionField': {'step': 1},
'products': cart.items.map(function(item) {
return {
'id': item.product.id.toString(),
'name': item.product.name,
'price': item.price,
'quantity': item.quantity
};
})
}
},
'cart': {
'total': cart.total,
'itemCount': cart.items.length,
'currency': cart.currency || 'USD'
}
});
});
}
});
// Cart Changed (Add to Cart / Remove from Cart)
var previousCart = null;
Ecwid.OnCartChanged.add(function(cart) {
if (previousCart === null) {
previousCart = JSON.parse(JSON.stringify(cart));
return;
}
// Item Added
if (cart.items.length > previousCart.items.length) {
var newItem = cart.items[cart.items.length - 1];
dataLayer.push({
'event': 'add_to_cart',
'ecommerce': {
'currencyCode': cart.currency || 'USD',
'add': {
'products': [{
'id': newItem.product.id.toString(),
'name': newItem.product.name,
'price': newItem.price,
'quantity': newItem.quantity
}]
}
},
'product': {
'id': newItem.product.id,
'name': newItem.product.name,
'price': newItem.price,
'quantity': newItem.quantity
}
});
}
// Item Removed
if (cart.items.length < previousCart.items.length) {
var removedItem = previousCart.items.find(function(prevItem) {
return !cart.items.some(function(currItem) {
return currItem.id === prevItem.id;
});
});
if (removedItem) {
dataLayer.push({
'event': 'remove_from_cart',
'ecommerce': {
'currencyCode': cart.currency || 'USD',
'remove': {
'products': [{
'id': removedItem.product.id.toString(),
'name': removedItem.product.name,
'price': removedItem.price,
'quantity': removedItem.quantity
}]
}
}
});
}
}
// Update cart reference
previousCart = JSON.parse(JSON.stringify(cart));
// Push cart data
dataLayer.push({
'event': 'cart_updated',
'cart': {
'total': cart.total,
'itemCount': cart.items.length,
'currency': cart.currency || 'USD',
'items': cart.items.map(function(item) {
return {
'id': item.product.id,
'name': item.product.name,
'price': item.price,
'quantity': item.quantity
};
})
}
});
});
// Order Placed (Purchase)
Ecwid.OnOrderPlaced.add(function(order) {
dataLayer.push({
'event': 'purchase',
'ecommerce': {
'currencyCode': order.currency || 'USD',
'purchase': {
'actionField': {
'id': order.vendorOrderNumber,
'affiliation': 'Ecwid Store',
'revenue': order.total,
'tax': order.tax || 0,
'shipping': order.shippingOption ? order.shippingOption.shippingRate : 0,
'coupon': order.couponDiscount > 0 ? order.couponName : ''
},
'products': order.items.map(function(item) {
return {
'id': item.product.id.toString(),
'name': item.product.name,
'price': item.price,
'quantity': item.quantity,
'category': item.product.categoryIds ? 'Category ' + item.product.categoryIds[0] : ''
};
})
}
},
'transaction': {
'id': order.vendorOrderNumber,
'total': order.total,
'tax': order.tax || 0,
'shipping': order.shippingOption ? order.shippingOption.shippingRate : 0,
'currency': order.currency || 'USD',
'email': order.email,
'itemCount': order.items.length
}
});
});
// Helper function
function getCategoryName(categoryIds) {
if (!categoryIds || categoryIds.length === 0) return '';
return 'Category ' + categoryIds[0];
}
});
</script>
Add this code to Ecwid's Custom JavaScript Code section to enable all data layer events.
Ecwid Data Layer Events
1. ecwid_loaded
Fires when Ecwid API is ready.
Data Layer Push:
{
'event': 'ecwid_loaded',
'ecwid_store_id': 12345678
}
GTM Trigger:
- Type: Custom Event
- Event name:
ecwid_loaded
Use case: Initialize tags that depend on Ecwid being loaded.
2. product_viewed
Fires when customer views a product detail page.
Data Layer Push:
{
'event': 'product_viewed',
'ecommerce': {
'currencyCode': 'USD',
'detail': {
'products': [{
'id': '123456',
'name': 'Product Name',
'price': 29.99,
'brand': 'Brand Name',
'category': 'Category Name',
'variant': 'SKU-123'
}]
}
},
'product': {
'id': 123456,
'name': 'Product Name',
'price': 29.99,
'currency': 'USD',
'inStock': true,
'url': 'https://store.com/product'
}
}
GTM Variables:
Create Data Layer Variables:
ecommerce.detail.products.0.id→ "Product ID"ecommerce.detail.products.0.name→ "Product Name"ecommerce.detail.products.0.price→ "Product Price"product.inStock→ "Product In Stock"
GTM Trigger:
- Type: Custom Event
- Event name:
product_viewed
3. category_viewed
Fires when customer views a category page.
Data Layer Push:
{
'event': 'category_viewed',
'category': {
'id': 12345,
'name': 'Category Name'
}
}
GTM Variables:
category.id→ "Category ID"category.name→ "Category Name"
GTM Trigger:
- Type: Custom Event
- Event name:
category_viewed
4. search_performed
Fires when customer uses search.
Data Layer Push:
{
'event': 'search_performed',
'search': {
'term': 'customer search query'
}
}
GTM Variable:
search.term→ "Search Term"
GTM Trigger:
- Type: Custom Event
- Event name:
search_performed
5. add_to_cart
Fires when item is added to cart.
Data Layer Push:
{
'event': 'add_to_cart',
'ecommerce': {
'currencyCode': 'USD',
'add': {
'products': [{
'id': '123456',
'name': 'Product Name',
'price': 29.99,
'quantity': 1
}]
}
},
'product': {
'id': 123456,
'name': 'Product Name',
'price': 29.99,
'quantity': 1
}
}
GTM Variables:
ecommerce.add.products.0.id→ "Added Product ID"ecommerce.add.products.0.name→ "Added Product Name"ecommerce.add.products.0.price→ "Added Product Price"product.quantity→ "Added Product Quantity"
GTM Trigger:
- Type: Custom Event
- Event name:
add_to_cart
6. remove_from_cart
Fires when item is removed from cart.
Data Layer Push:
{
'event': 'remove_from_cart',
'ecommerce': {
'currencyCode': 'USD',
'remove': {
'products': [{
'id': '123456',
'name': 'Product Name',
'price': 29.99,
'quantity': 1
}]
}
}
}
GTM Trigger:
- Type: Custom Event
- Event name:
remove_from_cart
7. cart_updated
Fires whenever cart changes (add, remove, quantity change).
Data Layer Push:
{
'event': 'cart_updated',
'cart': {
'total': 89.97,
'itemCount': 3,
'currency': 'USD',
'items': [
{
'id': 123456,
'name': 'Product 1',
'price': 29.99,
'quantity': 2
},
{
'id': 789012,
'name': 'Product 2',
'price': 29.99,
'quantity': 1
}
]
}
}
GTM Variables:
cart.total→ "Cart Total"cart.itemCount→ "Cart Item Count"cart.currency→ "Cart Currency"
GTM Trigger:
- Type: Custom Event
- Event name:
cart_updated
8. checkout_started
Fires when checkout process begins.
Data Layer Push:
{
'event': 'checkout_started',
'ecommerce': {
'currencyCode': 'USD',
'checkout': {
'actionField': {'step': 1},
'products': [{
'id': '123456',
'name': 'Product Name',
'price': 29.99,
'quantity': 1
}]
}
},
'cart': {
'total': 29.99,
'itemCount': 1,
'currency': 'USD'
}
}
GTM Trigger:
- Type: Custom Event
- Event name:
checkout_started
9. purchase
Fires when order is completed.
Data Layer Push:
{
'event': 'purchase',
'ecommerce': {
'currencyCode': 'USD',
'purchase': {
'actionField': {
'id': 'ORDER-12345',
'affiliation': 'Ecwid Store',
'revenue': 89.97,
'tax': 7.50,
'shipping': 10.00,
'coupon': 'SAVE10'
},
'products': [{
'id': '123456',
'name': 'Product Name',
'price': 29.99,
'quantity': 3,
'category': 'Category Name'
}]
}
},
'transaction': {
'id': 'ORDER-12345',
'total': 89.97,
'tax': 7.50,
'shipping': 10.00,
'currency': 'USD',
'email': 'customer@example.com',
'itemCount': 3
}
}
GTM Variables:
ecommerce.purchase.actionField.id→ "Transaction ID"ecommerce.purchase.actionField.revenue→ "Transaction Revenue"transaction.email→ "Customer Email"
GTM Trigger:
- Type: Custom Event
- Event name:
purchase
Creating GTM Variables
Data Layer Variables
For simple values directly in data layer:
Example: Product ID
- Variables → New
- Variable Type: Data Layer Variable
- Data Layer Variable Name:
ecommerce.detail.products.0.id - Data Layer Version: Version 2
- Name:
DLV - Product ID - Save
Example: Cart Total
- Variables → New
- Variable Type: Data Layer Variable
- Data Layer Variable Name:
cart.total - Name:
DLV - Cart Total - Save
Custom JavaScript Variables
For complex transformations:
Example: Product Items Array for GA4
function() {
var dl = {{Event}};
// For product_viewed
if (dl && dl.ecommerce && dl.ecommerce.detail) {
var products = dl.ecommerce.detail.products || [];
return products.map(function(p) {
return {
item_id: p.id,
item_name: p.name,
item_brand: p.brand || '',
item_category: p.category || '',
price: parseFloat(p.price),
quantity: 1
};
});
}
// For add_to_cart
if (dl && dl.ecommerce && dl.ecommerce.add) {
var products = dl.ecommerce.add.products || [];
return products.map(function(p) {
return {
item_id: p.id,
item_name: p.name,
price: parseFloat(p.price),
quantity: p.quantity
};
});
}
return [];
}
Variable Type: Custom JavaScript
Name: CJS - GA4 Items Array
Common GTM Variables for Ecwid
Create these variables for easy reuse:
| Variable Name | Type | Data Layer Path |
|---|---|---|
DLV - Product ID |
Data Layer | ecommerce.detail.products.0.id |
DLV - Product Name |
Data Layer | ecommerce.detail.products.0.name |
DLV - Product Price |
Data Layer | ecommerce.detail.products.0.price |
DLV - Product Category |
Data Layer | ecommerce.detail.products.0.category |
DLV - Cart Total |
Data Layer | cart.total |
DLV - Cart Item Count |
Data Layer | cart.itemCount |
DLV - Currency |
Data Layer | ecommerce.currencyCode |
DLV - Transaction ID |
Data Layer | ecommerce.purchase.actionField.id |
DLV - Revenue |
Data Layer | ecommerce.purchase.actionField.revenue |
DLV - Search Term |
Data Layer | search.term |
Creating GTM Triggers
Product Viewed Trigger
Trigger Configuration:
- Type: Custom Event
- Event name:
product_viewed
Name: Ecwid - Product Viewed
Add to Cart Trigger
Trigger Configuration:
- Type: Custom Event
- Event name:
add_to_cart
Name: Ecwid - Add to Cart
Purchase Trigger
Trigger Configuration:
- Type: Custom Event
- Event name:
purchase
Name: Ecwid - Purchase
All Ecwid Triggers
Create triggers for:
ecwid_loadedproduct_viewedcategory_viewedsearch_performedadd_to_cartremove_from_cartcart_updatedcheckout_startedpurchase
Example Tag Configurations
GA4 View Item Event
Tag Type: Google Analytics: GA4 Event
Configuration:
- Configuration Tag: GA4 - Configuration
- Event Name:
view_item
Event Parameters:
currency:\{\{DLV - Currency\}\}value:\{\{DLV - Product Price\}\}items:\{\{CJS - GA4 Items Array\}\}
Trigger: Ecwid - Product Viewed
GA4 Purchase Event
Tag Type: Google Analytics: GA4 Event
Configuration:
- Configuration Tag: GA4 - Configuration
- Event Name:
purchase
Event Parameters:
transaction_id:\{\{DLV - Transaction ID\}\}value:\{\{DLV - Revenue\}\}currency:\{\{DLV - Currency\}\}tax:\{\{ecommerce.purchase.actionField.tax\}\}shipping:\{\{ecommerce.purchase.actionField.shipping\}\}items:\{\{CJS - GA4 Purchase Items Array\}\}
Trigger: Ecwid - Purchase
Meta Pixel ViewContent Event
Tag Type: Custom HTML
HTML:
<script>
fbq('track', 'ViewContent', {
content_ids: ['{{DLV - Product ID}}'],
content_name: '{{DLV - Product Name}}',
content_type: 'product',
value: {{DLV - Product Price}},
currency: '{{DLV - Currency}}'
});
</script>
Trigger: Ecwid - Product Viewed
Debugging Data Layer
View Data Layer in Console
// View entire data layer
console.table(window.dataLayer);
// Filter specific event
window.dataLayer.filter(obj => obj.event === 'product_viewed');
// Monitor new pushes
var originalPush = window.dataLayer.push;
window.dataLayer.push = function() {
console.log('Data Layer Push:', arguments[0]);
return originalPush.apply(window.dataLayer, arguments);
};
GTM Preview Mode
- Enable Preview in GTM
- Navigate to store
- Click event in Tag Assistant
- View Data Layer tab
- Verify values populate
Common Issues
Data Layer is Empty
Cause: Ecwid API not loaded or data layer code not added.
Fix:
- Add complete data layer implementation code (see above)
- Verify code is in Custom JavaScript Code section
- Check console for JavaScript errors
Variables Return Undefined
Cause: Data layer path incorrect or event hasn't fired.
Fix:
- Verify exact data layer path
- Check that event has fired before variable accessed
- Use GTM Preview to inspect data layer
Events Fire Multiple Times
Cause: Multiple data layer implementations or page reloads.
Fix:
- Use flags to prevent duplicates
- Check for multiple GTM containers
- Remove duplicate implementations
Best Practices
1. Clear Event Names
Use descriptive, consistent event names:
product_viewed(notproductVieworview_product)add_to_cart(notaddCartorcartAdd)
2. Consistent Data Structure
Keep ecommerce object structure consistent across events.
3. Include Currency
Always include currency code with monetary values.
4. String vs Number
- IDs: Always strings
- Prices: Always numbers
- Quantities: Always numbers
5. Error Handling
Add error handling to data layer code:
try {
dataLayer.push({...});
} catch (e) {
console.error('Data Layer Push Error:', e);
}
Next Steps
- GTM Setup - Install GTM on Ecwid
- GA4 Event Tracking - Use data layer for GA4
- Events Not Firing - Debug tracking issues
For general data layer concepts, see Data Layer Guide.