Overview
Meta Pixel events track user interactions for:
- Conversion optimization
- Custom audience building
- Dynamic ads retargeting
- Attribution and ROI measurement
Event types:
- Standard Events: Predefined Facebook events (Purchase, AddToCart, etc.)
- Custom Events: User-defined events for specific actions
- Custom Parameters: Additional data sent with events
Standard Events for Ecommerce
Core Conversion Events
Meta recommends these events for ecommerce:
| Event | Description | When to Fire |
|---|---|---|
ViewContent |
Product page view | Product detail page load |
Search |
Search performed | Search results displayed |
AddToCart |
Product added to cart | Add to cart button clicked |
AddToWishlist |
Product added to wishlist | Wishlist button clicked |
InitiateCheckout |
Checkout started | Checkout page loaded |
AddPaymentInfo |
Payment method added | Payment step completed |
Purchase |
Order completed | Success page loaded |
Lead |
Lead form submitted | Contact/newsletter signup |
ViewContent Event
Track product detail page views for dynamic ads and retargeting.
Implementation
File: catalog/controller/product/product.php
Add to index() method after product data is loaded:
// Facebook Pixel ViewContent event data
if ($product_info) {
// Get product category
$categories = $this->model_catalog_product->getCategories($product_id);
$category_name = '';
if ($categories) {
$this->load->model('catalog/category');
$category_info = $this->model_catalog_category->getCategory($categories[0]['category_id']);
$category_name = $category_info ? $category_info['name'] : '';
}
// Format price without currency symbols
$price = $this->currency->format(
$product_info['price'],
$this->session->data['currency'],
'',
false
);
$data['fb_view_content'] = array(
'content_ids' => array($product_info['product_id']),
'content_name' => $product_info['name'],
'content_category' => $category_name,
'content_type' => 'product',
'value' => $price,
'currency' => $this->session->data['currency']
);
}
File: catalog/view/theme/[your-theme]/template/product/product.twig
Add after opening <body> tag or before closing </body>:
{% if fb_view_content %}
<script>
fbq('track', 'ViewContent', {
content_ids: {{ fb_view_content.content_ids|json_encode|raw }},
content_name: '{{ fb_view_content.content_name|escape('js') }}',
content_category: '{{ fb_view_content.content_category|escape('js') }}',
content_type: '{{ fb_view_content.content_type }}',
value: {{ fb_view_content.value }},
currency: '{{ fb_view_content.currency }}'
});
</script>
{% endif %}
Search Event
Track site searches to understand user intent.
Implementation
File: catalog/controller/product/search.php
Add to index() method:
// Facebook Pixel Search event
if (isset($this->request->get['search'])) {
$data['fb_search'] = array(
'search_string' => $this->request->get['search'],
'content_type' => 'product'
);
}
File: catalog/view/theme/[your-theme]/template/product/search.twig
{% if fb_search %}
<script>
fbq('track', 'Search', {
search_string: '{{ fb_search.search_string|escape('js') }}',
content_type: '{{ fb_search.content_type }}'
});
</script>
{% endif %}
Alternative: Client-Side Search Tracking
File: catalog/view/theme/[your-theme]/template/common/search.twig
<script>
$(document).ready(function() {
$('header #search input[name="search"]').closest('form').on('submit', function() {
var searchTerm = $(this).find('input[name="search"]').val();
if (searchTerm) {
fbq('track', 'Search', {
search_string: searchTerm,
content_type: 'product'
});
}
});
});
</script>
AddToCart Event
Critical event for conversion optimization and dynamic product ads.
Method 1: Product Page Add to Cart
File: catalog/view/theme/[your-theme]/template/product/product.twig
<script>
$('#button-cart').on('click', function() {
// Get product data
var productId = $('input[name="product_id"]').val();
var productName = $('h1').first().text().trim();
var quantity = parseInt($('input[name="quantity"]').val());
// Get price (handle special/discount prices)
var priceText = $('.price-new').length ? $('.price-new').text() : $('.price').text();
var price = parseFloat(priceText.replace(/[^0-9.]/g, ''));
// Track AddToCart
fbq('track', 'AddToCart', {
content_ids: [productId],
content_name: productName,
content_type: 'product',
value: price * quantity,
currency: '{{ currency_code }}'
});
});
</script>
Method 2: AJAX Add to Cart (Cart Module)
For add to cart from category pages and quick-add buttons:
File: catalog/view/theme/[your-theme]/template/common/cart.twig
Modify the cart.add function:
<script>
var cart = {
'add': function(product_id, quantity) {
$.ajax({
url: 'index.php?route=checkout/cart/add',
type: 'post',
data: 'product_id=' + product_id + '&quantity=' + (typeof(quantity) != 'undefined' ? quantity : 1),
dataType: 'json',
beforeSend: function() {
$('#cart > button').button('loading');
},
complete: function() {
$('#cart > button').button('reset');
},
success: function(json) {
if (json['success']) {
// Get product info from the button's context
var productName = $('[onclick*="cart.add(' + product_id + ')"]')
.closest('.product-thumb')
.find('.caption h4 a')
.text()
.trim();
var priceText = $('[onclick*="cart.add(' + product_id + ')"]')
.closest('.product-thumb')
.find('.price')
.text();
var price = parseFloat(priceText.replace(/[^0-9.]/g, ''));
var qty = typeof(quantity) != 'undefined' ? quantity : 1;
// Track AddToCart
fbq('track', 'AddToCart', {
content_ids: [product_id],
content_name: productName,
content_type: 'product',
value: price * qty,
currency: '{{ currency_code }}'
});
// Original success notification
$('#cart > button').html('<i class="fa fa-shopping-cart"></i> ' + json['total']);
$('html, body').animate({ scrollTop: 0 }, 'slow');
$('#cart > ul').load('index.php?route=common/cart/info ul li');
}
}
});
}
};
</script>
Method 3: Server-Side with Product Data
File: catalog/controller/checkout/cart.php
Add to add() method:
public function add() {
// Original add to cart logic...
if ($this->cart->hasProducts()) {
// Get the product that was just added
$product_id = isset($this->request->post['product_id']) ? (int)$this->request->post['product_id'] : 0;
$quantity = isset($this->request->post['quantity']) ? (int)$this->request->post['quantity'] : 1;
if ($product_id) {
$this->load->model('catalog/product');
$product_info = $this->model_catalog_product->getProduct($product_id);
if ($product_info) {
$json['fb_add_to_cart'] = array(
'content_ids' => array($product_id),
'content_name' => $product_info['name'],
'content_type' => 'product',
'value' => $this->currency->format($product_info['price'], $this->session->data['currency'], '', false) * $quantity,
'currency' => $this->session->data['currency']
);
}
}
}
// Return JSON response
$this->response->addHeader('Content-Type: application/json');
$this->response->setOutput(json_encode($json));
}
Then in JavaScript:
success: function(json) {
if (json['success'] && json['fb_add_to_cart']) {
fbq('track', 'AddToCart', json['fb_add_to_cart']);
}
}
AddToWishlist Event
Track wishlist additions for retargeting.
Implementation
File: catalog/view/theme/[your-theme]/template/product/product.twig
<script>
// Track wishlist button click
$(document).on('click', 'button[onclick*="wishlist.add"]', function() {
var productId = $('input[name="product_id"]').val();
var productName = $('h1').first().text().trim();
var priceText = $('.price-new').length ? $('.price-new').text() : $('.price').text();
var price = parseFloat(priceText.replace(/[^0-9.]/g, ''));
fbq('track', 'AddToWishlist', {
content_ids: [productId],
content_name: productName,
content_type: 'product',
value: price,
currency: '{{ currency_code }}'
});
});
</script>
Category Page Wishlist
<script>
$(document).on('click', 'button[onclick*="wishlist.add"]', function() {
var
var productId = onclick.match(/wishlist\.add\('(\d+)'\)/)[1];
var productThumb = $(this).closest('.product-thumb');
var productName = productThumb.find('.caption h4 a').text().trim();
var priceText = productThumb.find('.price').text();
var price = parseFloat(priceText.replace(/[^0-9.]/g, ''));
fbq('track', 'AddToWishlist', {
content_ids: [productId],
content_name: productName,
content_type: 'product',
value: price,
currency: '{{ currency_code }}'
});
});
</script>
InitiateCheckout Event
Track when checkout process begins.
Implementation
File: catalog/controller/checkout/checkout.php
Add to index() method:
// Get cart items for Facebook Pixel
$data['fb_cart_items'] = array();
$cart_value = 0;
$content_ids = array();
foreach ($this->cart->getProducts() as $product) {
$price = $this->currency->format($product['price'], $this->session->data['currency'], '', false);
$cart_value += $price * $product['quantity'];
$content_ids[] = $product['product_id'];
}
$data['fb_initiate_checkout'] = array(
'content_ids' => $content_ids,
'content_type' => 'product',
'value' => $cart_value,
'currency' => $this->session->data['currency'],
'num_items' => count($content_ids)
);
File: catalog/view/theme/[your-theme]/template/checkout/checkout.twig
{% if fb_initiate_checkout %}
<script>
fbq('track', 'InitiateCheckout', {
content_ids: {{ fb_initiate_checkout.content_ids|json_encode|raw }},
content_type: '{{ fb_initiate_checkout.content_type }}',
value: {{ fb_initiate_checkout.value }},
currency: '{{ fb_initiate_checkout.currency }}',
num_items: {{ fb_initiate_checkout.num_items }}
});
</script>
{% endif %}
AddPaymentInfo Event
Track payment method selection (optional but recommended).
Implementation
File: catalog/view/theme/[your-theme]/template/checkout/checkout.twig
<script>
// Track when payment method is selected
$(document).on('click', '#button-payment-method', function() {
var cartValue = {{ fb_initiate_checkout.value|default(0) }};
var contentIds = {{ fb_initiate_checkout.content_ids|default([])|json_encode|raw }};
fbq('track', 'AddPaymentInfo', {
content_ids: contentIds,
content_type: 'product',
value: cartValue,
currency: '{{ currency_code }}'
});
});
</script>
Purchase Event
Most important event - tracks completed transactions.
Implementation
File: catalog/controller/checkout/success.php
Add to index() method:
// Get order ID from session
$order_id = isset($this->session->data['order_id']) ? $this->session->data['order_id'] : 0;
if ($order_id && !isset($this->session->data['fb_tracked_' . $order_id])) {
$this->load->model('checkout/order');
$order_info = $this->model_checkout_order->getOrder($order_id);
if ($order_info) {
// Get order products
$order_products = $this->model_checkout_order->getOrderProducts($order_id);
$content_ids = array();
$contents = array();
foreach ($order_products as $product) {
$content_ids[] = $product['product_id'];
$contents[] = array(
'id' => $product['product_id'],
'quantity' => $product['quantity']
);
}
$data['fb_purchase'] = array(
'content_ids' => $content_ids,
'contents' => $contents,
'content_type' => 'product',
'value' => $this->currency->format($order_info['total'], $order_info['currency_code'], '', false),
'currency' => $order_info['currency_code'],
'num_items' => count($content_ids)
);
// Mark as tracked to prevent duplicates
$this->session->data['fb_tracked_' . $order_id] = true;
}
// Clear order_id from session
unset($this->session->data['order_id']);
}
File: catalog/view/theme/[your-theme]/template/common/success.twig
{% if fb_purchase %}
<script>
fbq('track', 'Purchase', {
content_ids: {{ fb_purchase.content_ids|json_encode|raw }},
contents: {{ fb_purchase.contents|json_encode|raw }},
content_type: '{{ fb_purchase.content_type }}',
value: {{ fb_purchase.value }},
currency: '{{ fb_purchase.currency }}',
num_items: {{ fb_purchase.num_items }}
});
</script>
{% endif %}
Lead Event
Track newsletter signups and contact form submissions.
Newsletter Signup
File: catalog/view/theme/[your-theme]/template/common/footer.twig
<script>
$(document).on('submit', '#newsletter-form', function(e) {
// Track before submission
fbq('track', 'Lead', {
content_name: 'Newsletter Subscription',
content_category: 'Newsletter',
value: 0.00,
currency: '{{ currency_code }}'
});
});
</script>
Contact Form
File: catalog/view/theme/[your-theme]/template/information/contact.twig
<script>
$(document).on('submit', '#contact-form', function() {
fbq('track', 'Lead', {
content_name: 'Contact Form',
content_category: 'Contact',
value: 0.00,
currency: '{{ currency_code }}'
});
});
</script>
Custom Events
Track business-specific actions.
Account Registration
File: catalog/view/theme/[your-theme]/template/account/register.twig
<script>
$(document).on('submit', '#register-form', function() {
fbq('trackCustom', 'AccountCreation', {
content_name: 'New Account Registration'
});
});
</script>
Product Reviews
File: catalog/view/theme/[your-theme]/template/product/product.twig
<script>
$(document).on('submit', '#form-review', function() {
var productId = $('input[name="product_id"]').val();
var productName = $('h1').first().text().trim();
fbq('trackCustom', 'ProductReview', {
content_ids: [productId],
content_name: productName
});
});
</script>
Download Product Files
<script>
$(document).on('click', 'a[href*="download"]', function() {
var fileName = $(this).text().trim();
fbq('trackCustom', 'Download', {
content_name: fileName,
content_type: 'digital_product'
});
});
</script>
Event Testing
Facebook Pixel Helper
- Install Meta Pixel Helper
- Visit your store
- Trigger events (add to cart, checkout, etc.)
- Check extension icon for event detection
- Click for detailed event parameters
Test Events Tool
Facebook Events Manager > [Your Pixel] > Test Events
- Enter website URL or use browser extension
- Perform actions on your site
- Events appear in real-time
- Verify parameters are correct
Browser Console Testing
// Check fbq function exists
console.log(typeof fbq); // Should return "function"
// Manually trigger test event
fbq('track', 'AddToCart', {
content_ids: ['123'],
content_type: 'product',
value: 29.99,
currency: 'USD'
});
// Check event queue
console.log(_fbq.instance.pixelsByID);
Event Deduplication
Prevent duplicate events when using multiple pixels or Conversions API:
<script>
// Generate unique event ID
var eventID = 'event_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
fbq('track', 'Purchase', {
content_ids: ['123'],
value: 29.99,
currency: 'USD'
}, {
eventID: eventID
});
// Send same eventID to Conversions API server-side
// This prevents double-counting
</script>
Common Issues
Events Not Firing
Problem: Events don't appear in Test Events
Solutions:
- Check
fbqfunction is loaded:console.log(typeof fbq) - Verify Pixel initialization before event tracking
- Check JavaScript console for errors
- Test with Pixel Helper extension
- Ensure ad blockers are disabled
Incorrect Parameters
Problem: Event fires but parameters are wrong
Solutions:
- Console.log variables before passing to fbq:
console.log('Product ID:', productId); console.log('Price:', price); - Verify data types (value should be number, not string)
- Check currency code is valid ISO 4217
- Ensure content_ids is an array
Duplicate Events
Problem: Same event fires multiple times
Solutions:
- Use
.off()before.on()for event handlers - Implement event deduplication with eventID
- Check for multiple tracking codes
- Verify event isn't in multiple theme files