Comprehensive guide to implementing Meta Pixel (Facebook Pixel) event tracking on Ecwid stores using the Ecwid JavaScript API.
Meta Pixel Standard Events
Meta provides standard events optimized for advertising and conversion tracking.
Standard Events for Ecommerce
| Event | When to Fire | Required Parameters |
|---|---|---|
ViewContent |
Product page viewed | content_ids, content_type, value, currency |
Search |
Search performed | search_string |
AddToCart |
Item added to cart | content_ids, content_type, value, currency |
AddToWishlist |
Item added to wishlist | content_ids, content_type, value, currency |
InitiateCheckout |
Checkout started | content_ids, contents, value, currency, num_items |
AddPaymentInfo |
Payment info added | content_ids, contents, value, currency |
Purchase |
Order completed | content_ids, contents, value, currency, num_items |
Lead |
Lead form submitted | None required |
CompleteRegistration |
Account created | None required |
Event Data Structure
All events follow this structure:
fbq('track', 'EventName', {
content_ids: ['123', '456'], // Array of product IDs (strings)
content_name: 'Product Name', // Optional
content_type: 'product', // 'product' or 'product_group'
contents: [ // Array of product objects
{id: '123', quantity: 2},
{id: '456', quantity: 1}
],
value: 29.99, // Number without currency symbol
currency: 'USD', // 3-letter ISO code
num_items: 3 // Total quantity
});
Standard Event Implementation
Add to Ecwid's Custom JavaScript Code section (Settings → General → Tracking & Analytics).
1. ViewContent (Product Views)
Fire when customer views a product detail page:
Ecwid.OnAPILoaded.add(function() {
Ecwid.OnPageLoad.add(function(page) {
if (page.type === 'PRODUCT') {
Ecwid.getProduct(page.productId, function(product) {
fbq('track', 'ViewContent', {
content_ids: [product.id.toString()],
content_name: product.name,
content_category: getCategoryName(product.categoryIds),
content_type: 'product',
value: product.defaultDisplayedPrice,
currency: product.currency || 'USD'
});
});
}
});
// Helper function
function getCategoryName(categoryIds) {
if (!categoryIds || categoryIds.length === 0) return '';
return 'Category ' + categoryIds[0];
}
});
2. Search
Fire when customer uses search:
Ecwid.OnAPILoaded.add(function() {
Ecwid.OnPageLoad.add(function(page) {
if (page.type === 'SEARCH' && page.keywords) {
fbq('track', 'Search', {
search_string: page.keywords
});
}
});
});
3. AddToCart
Fire when item is added to cart:
Ecwid.OnAPILoaded.add(function() {
var previousCart = null;
Ecwid.OnCartChanged.add(function(cart) {
// Initialize previous cart
if (previousCart === null) {
previousCart = JSON.parse(JSON.stringify(cart));
return;
}
// Detect new items added
if (cart.items.length > previousCart.items.length) {
// Find the newly added item
var newItem = cart.items.find(function(cartItem) {
return !previousCart.items.some(function(prevItem) {
return prevItem.id === cartItem.id;
});
});
if (newItem) {
fbq('track', 'AddToCart', {
content_ids: [newItem.product.id.toString()],
content_name: newItem.product.name,
content_type: 'product',
contents: [{
id: newItem.product.id.toString(),
quantity: newItem.quantity,
item_price: newItem.price
}],
value: newItem.price * newItem.quantity,
currency: cart.currency || 'USD'
});
}
}
// Detect quantity increases
if (cart.items.length === previousCart.items.length) {
cart.items.forEach(function(cartItem) {
var prevItem = previousCart.items.find(function(prev) {
return prev.id === cartItem.id;
});
if (prevItem && cartItem.quantity > prevItem.quantity) {
var qtyAdded = cartItem.quantity - prevItem.quantity;
fbq('track', 'AddToCart', {
content_ids: [cartItem.product.id.toString()],
content_name: cartItem.product.name,
content_type: 'product',
contents: [{
id: cartItem.product.id.toString(),
quantity: qtyAdded,
item_price: cartItem.price
}],
value: cartItem.price * qtyAdded,
currency: cart.currency || 'USD'
});
}
});
}
// Update reference
previousCart = JSON.parse(JSON.stringify(cart));
});
});
4. InitiateCheckout
Fire when checkout process starts:
Ecwid.OnAPILoaded.add(function() {
var checkoutStarted = false;
Ecwid.OnPageLoad.add(function(page) {
// Checkout starts at address page
if (page.type === 'CHECKOUT_ADDRESS' && !checkoutStarted) {
checkoutStarted = true;
Ecwid.Cart.get(function(cart) {
fbq('track', 'InitiateCheckout', {
content_ids: cart.items.map(function(item) {
return item.product.id.toString();
}),
contents: cart.items.map(function(item) {
return {
id: item.product.id.toString(),
quantity: item.quantity,
item_price: item.price
};
}),
content_type: 'product',
value: cart.total,
currency: cart.currency || 'USD',
num_items: cart.items.reduce(function(sum, item) {
return sum + item.quantity;
}, 0)
});
});
}
// Reset flag when leaving checkout
if (page.type !== 'CHECKOUT_ADDRESS' &&
page.type !== 'CHECKOUT_SHIPPING' &&
page.type !== 'CHECKOUT_PAYMENT') {
checkoutStarted = false;
}
});
});
5. AddPaymentInfo
Fire when customer enters payment step:
Ecwid.OnAPILoaded.add(function() {
var paymentInfoAdded = false;
Ecwid.OnPageLoad.add(function(page) {
if (page.type === 'CHECKOUT_PAYMENT' && !paymentInfoAdded) {
paymentInfoAdded = true;
Ecwid.Cart.get(function(cart) {
fbq('track', 'AddPaymentInfo', {
content_ids: cart.items.map(function(item) {
return item.product.id.toString();
}),
contents: cart.items.map(function(item) {
return {
id: item.product.id.toString(),
quantity: item.quantity,
item_price: item.price
};
}),
content_type: 'product',
value: cart.total,
currency: cart.currency || 'USD'
});
});
}
// Reset when leaving payment page
if (page.type !== 'CHECKOUT_PAYMENT') {
paymentInfoAdded = false;
}
});
});
6. Purchase
Fire when order is successfully completed:
Ecwid.OnAPILoaded.add(function() {
var purchaseTracked = false;
Ecwid.OnOrderPlaced.add(function(order) {
// Prevent duplicate tracking
if (purchaseTracked) return;
purchaseTracked = true;
fbq('track', 'Purchase', {
content_ids: order.items.map(function(item) {
return item.product.id.toString();
}),
contents: order.items.map(function(item) {
return {
id: item.product.id.toString(),
quantity: item.quantity,
item_price: item.price
};
}),
content_type: 'product',
value: order.total,
currency: order.currency || 'USD',
num_items: order.items.reduce(function(sum, item) {
return sum + item.quantity;
}, 0)
}, {
eventID: 'order-' + order.vendorOrderNumber // For deduplication with CAPI
});
// Reset after delay
setTimeout(function() {
purchaseTracked = false;
}, 5000);
});
});
Custom Events
Track custom interactions specific to your store.
CompleteRegistration (Account Creation)
Track when customers create accounts:
Ecwid.OnAPILoaded.add(function() {
var registrationTracked = false;
Ecwid.OnPageLoad.add(function(page) {
if (page.type === 'ACCOUNT_SETTINGS') {
Ecwid.getCustomerInfo(function(customer) {
if (customer && customer.id && !registrationTracked) {
registrationTracked = true;
fbq('track', 'CompleteRegistration', {
content_name: 'Customer Account',
status: 'completed'
});
}
});
}
});
});
AddToWishlist (Custom Wishlist)
If you implement a custom wishlist feature:
function addToWishlist(productId, productName, productPrice) {
fbq('track', 'AddToWishlist', {
content_ids: [productId.toString()],
content_name: productName,
content_type: 'product',
value: productPrice,
currency: 'USD'
});
}
// Call when customer clicks wishlist button
document.querySelector('.wishlist-btn').addEventListener('click', function() {
var productId = this.dataset.productId;
var productName = this.dataset.productName;
var productPrice = parseFloat(this.dataset.productPrice);
addToWishlist(productId, productName, productPrice);
});
Subscribe (Newsletter Signup)
Track newsletter subscriptions:
// On host page newsletter form
document.getElementById('newsletter-form').addEventListener('submit', function(e) {
e.preventDefault();
fbq('track', 'Subscribe', {
content_name: 'Newsletter',
value: 0,
currency: 'USD',
predicted_ltv: 50.00 // Estimated customer lifetime value
});
// Submit form
this.submit();
});
Contact (Contact Form)
Track contact form submissions:
document.getElementById('contact-form').addEventListener('submit', function(e) {
fbq('track', 'Contact', {
content_name: 'Contact Form',
content_category: 'Customer Support'
});
});
Custom Event: Product Variant Selection
Track when customers select product options:
Ecwid.OnAPILoaded.add(function() {
Ecwid.OnPageLoad.add(function(page) {
if (page.type === 'PRODUCT') {
// Track variant selection on add to cart
Ecwid.OnCartChanged.add(function(cart) {
var lastItem = cart.items[cart.items.length - 1];
if (lastItem && lastItem.selectedOptions) {
fbq('trackCustom', 'VariantSelected', {
product_id: lastItem.product.id.toString(),
product_name: lastItem.product.name,
variant: lastItem.selectedOptions.map(function(opt) {
return opt.name + ': ' + opt.value;
}).join(', ')
});
}
});
}
});
});
Custom Event: Coupon Usage
Track when customers apply discount coupons:
Ecwid.OnAPILoaded.add(function() {
var previousCoupon = null;
Ecwid.OnCartChanged.add(function(cart) {
if (cart.couponDiscount && cart.couponDiscount > 0) {
if (cart.couponName !== previousCoupon) {
fbq('trackCustom', 'CouponApplied', {
coupon_code: cart.couponName,
discount_amount: cart.couponDiscount,
currency: cart.currency || 'USD'
});
previousCoupon = cart.couponName;
}
} else {
previousCoupon = null;
}
});
});
Advanced Tracking Patterns
Dynamic Product Ads (DPA)
Optimize for Dynamic Product Ads:
Ecwid.OnAPILoaded.add(function() {
// ViewContent with detailed product data
Ecwid.OnPageLoad.add(function(page) {
if (page.type === 'PRODUCT') {
Ecwid.getProduct(page.productId, function(product) {
fbq('track', 'ViewContent', {
content_ids: [product.id.toString()],
content_name: product.name,
content_category: getCategoryPath(product.categoryIds),
content_type: 'product',
value: product.defaultDisplayedPrice,
currency: product.currency || 'USD',
// Additional DPA parameters
availability: product.inStock ? 'in stock' : 'out of stock',
condition: 'new',
brand: product.brand || '',
price: product.defaultDisplayedPrice,
sale_price: product.compareToPrice > product.defaultDisplayedPrice ?
product.defaultDisplayedPrice : undefined
});
});
}
});
function getCategoryPath(categoryIds) {
if (!categoryIds || categoryIds.length === 0) return '';
// Fetch full category path if needed
return 'Category ' + categoryIds[0];
}
});
ViewCategory Event (Custom)
Track category page views for audience building:
Ecwid.OnAPILoaded.add(function() {
Ecwid.OnPageLoad.add(function(page) {
if (page.type === 'CATEGORY') {
fbq('trackCustom', 'ViewCategory', {
category_id: page.categoryId.toString(),
category_name: 'Category ' + page.categoryId // Or fetch actual name
});
}
});
});
Engagement Tracking
Track engagement metrics:
Ecwid.OnAPILoaded.add(function() {
var engagementStartTime = Date.now();
// Track time spent on product page
Ecwid.OnPageLoad.add(function(page) {
if (page.type === 'PRODUCT') {
engagementStartTime = Date.now();
} else {
var timeSpent = (Date.now() - engagementStartTime) / 1000;
// Track if spent more than 10 seconds
if (timeSpent > 10) {
fbq('trackCustom', 'ProductEngagement', {
time_spent: Math.round(timeSpent),
engaged: timeSpent > 30
});
}
}
});
});
Event Deduplication
Prevent duplicate events when using both browser pixel and Conversions API:
Browser Pixel with Event ID
Ecwid.OnAPILoaded.add(function() {
Ecwid.OnOrderPlaced.add(function(order) {
var eventID = 'order-' + order.vendorOrderNumber;
fbq('track', 'Purchase', {
// ... event parameters
}, {
eventID: eventID // Unique event identifier
});
});
});
Server-Side Conversions API
Use same eventID in your server-side request:
// In your webhook handler
{
event_name: 'Purchase',
event_id: 'order-' + order.vendorOrderNumber, // Same ID
event_time: Math.floor(Date.now() / 1000),
// ... rest of data
}
Meta will deduplicate events with matching event_id within 48 hours.
Advanced Matching
Send hashed customer data for better attribution:
Ecwid.OnAPILoaded.add(function() {
Ecwid.getCustomerInfo(function(customer) {
if (customer && customer.email) {
// Re-initialize pixel with advanced matching
fbq('init', '1234567890123456', {
em: customer.email.toLowerCase().trim(),
fn: customer.firstName ? customer.firstName.toLowerCase().trim() : undefined,
ln: customer.lastName ? customer.lastName.toLowerCase().trim() : undefined,
ph: customer.phone ? customer.phone.replace(/[^0-9]/g, '') : undefined,
external_id: customer.id.toString()
});
// Re-track PageView with customer data
fbq('track', 'PageView');
}
});
});
Note: Meta automatically hashes this data. Ensure privacy policy compliance.
Consent Management
Implement GDPR/CCPA compliant tracking:
Delayed Loading
Only load pixel after consent:
var pixelLoaded = false;
function loadMetaPixel() {
if (pixelLoaded) return;
pixelLoaded = true;
// Load base pixel code
!function(f,b,e,v,n,t,s){...}(window, document,'script',...);
fbq('init', '1234567890123456');
fbq('track', 'PageView');
// Initialize Ecwid tracking
initializeEcwidTracking();
}
// Call when user accepts cookies
document.getElementById('accept-cookies').addEventListener('click', function() {
loadMetaPixel();
});
function initializeEcwidTracking() {
Ecwid.OnAPILoaded.add(function() {
// All your Ecwid event tracking here
});
}
Limited Data Use
For California residents (CCPA):
fbq('dataProcessingOptions', ['LDU'], 1, 1000); // 1 = California, 1000 = state code
Revoke Consent
function revokeConsent() {
fbq('consent', 'revoke');
}
Debugging Events
Enable Test Mode
Use test event code for development:
fbq('init', '1234567890123456', {}, {
agent: 'test_agent', // Mark as test traffic
autoConfig: true
});
Console Logging
Log all events to console:
var originalFbq = window.fbq;
window.fbq = function() {
console.log('Meta Pixel Event:', arguments);
return originalFbq.apply(this, arguments);
};
Check Event Queue
// View all queued events
console.log(window._fbq.queue);
Testing Checklist
- Pixel loads - Meta Pixel Helper shows green icon
- PageView - Fires on all pages
- ViewContent - Fires on product pages with product data
- Search - Fires when search used
- AddToCart - Fires when item added, correct value
- InitiateCheckout - Fires once at checkout start
- AddPaymentInfo - Fires on payment page
- Purchase - Fires on order completion with correct total
- Event deduplication - No duplicate events
- Parameters correct - All required params present
- Currency correct - Matches store currency
- Content IDs - Are strings in array format
- Custom events - Fire as expected
Common Issues
Events Fire Multiple Times
Cause: Event listeners attached multiple times or page reloads.
Fix: Use flags to prevent duplicates:
var eventFired = false;
Ecwid.OnOrderPlaced.add(function(order) {
if (eventFired) return;
eventFired = true;
fbq('track', 'Purchase', {...});
setTimeout(function() {
eventFired = false;
}, 5000);
});
Missing content_ids
Cause: IDs not converted to strings or not in array.
Fix: Always format correctly:
// Wrong
content_ids: product.id,
// Correct
content_ids: [product.id.toString()],
Value includes currency symbol
Cause: Passing formatted price string instead of number.
Fix:
// Wrong
value: '$29.99',
// Correct
value: 29.99,
Ecwid API not available
Cause: Code runs before Ecwid loads.
Fix: Always wrap in Ecwid.OnAPILoaded.add():
Ecwid.OnAPILoaded.add(function() {
// All tracking code here
});
Meta Pixel Helper Error Messages
"Invalid or Missing Parameters"
Fix: Ensure all required parameters are present and formatted correctly.
"Duplicate Pixel Code"
Fix: Remove duplicate pixel implementations (check built-in integration, custom code, GTM).
"No Pixel Found"
Fix: Verify pixel code is in Custom JavaScript Code section and Pixel ID is correct.
Next Steps
- Meta Pixel Setup - Install Meta Pixel
- GTM Data Layer - Use GTM for easier management
- Events Not Firing - Debug tracking issues
For general Meta Pixel concepts, see Meta Pixel Guide.