Learn how to implement custom event tracking for Meta Pixel on Kentico Xperience, including standard events, custom events, and e-commerce tracking.
Prerequisites
- Meta Pixel Setup completed
- Understanding of Meta Pixel standard events
- Access to Kentico development environment
Standard Events Overview
Meta provides standard events for common actions:
| Event | Use Case |
|---|---|
ViewContent |
Product/content page views |
Search |
Search actions |
AddToCart |
Adding items to cart |
AddToWishlist |
Adding to wishlist |
InitiateCheckout |
Starting checkout |
AddPaymentInfo |
Adding payment info |
Purchase |
Completed purchase |
Lead |
Lead generation (form submission) |
CompleteRegistration |
User registration |
Contact |
Contact form submission |
Subscribe |
Newsletter/subscription |
Standard Event Implementation
ViewContent Event
Track product or content page views:
@using CMS.DocumentEngine
@using CMS.Ecommerce
@{
var currentDoc = DocumentContext.CurrentDocument;
}
@if (currentDoc.ClassName == "Custom.Product")
{
var product = (SKUInfo)currentDoc.GetValue("ProductSKU");
<script>
fbq('track', 'ViewContent', {
content_name: '@currentDoc.DocumentName',
content_category: '@currentDoc.GetValue("Category")',
content_ids: ['@product.SKUNumber'],
content_type: 'product',
value: @product.SKUPrice,
currency: '@CurrencyInfoProvider.GetMainCurrency(SiteContext.CurrentSiteID).CurrencyCode'
});
</script>
}
For Kentico E-commerce products:
@using CMS.Ecommerce
@model SKUInfo
<script>
fbq('track', 'ViewContent', {
content_name: '@Model.SKUName',
content_category: '@(Model.PrimaryCategory?.CategoryDisplayName ?? "")',
content_ids: ['@Model.SKUNumber'],
content_type: 'product',
value: @Model.SKUPrice,
currency: '@CurrencyInfoProvider.GetMainCurrency(SiteContext.CurrentSiteID).CurrencyCode'
});
</script>
Search Event
Track site searches:
@if (!string.IsNullOrEmpty(ViewBag.SearchQuery))
{
<script>
fbq('track', 'Search', {
search_string: '@ViewBag.SearchQuery',
content_category: '@ViewBag.SearchCategory',
content_ids: [@Html.Raw(string.Join(",", ViewBag.ResultIds.Select(id => $"'{id}'"))))]
});
</script>
}
AddToCart Event
Track when users add products to cart:
Client-Side (AJAX)
<script>
function addToCart(productId) {
// AJAX call to add product
$.ajax({
url: '/ShoppingCart/AddItem',
method: 'POST',
data: { skuId: productId, quantity: 1 },
success: function(response) {
// Track add to cart
fbq('track', 'AddToCart', {
content_name: response.product.name,
content_ids: [response.product.skuNumber],
content_type: 'product',
value: response.product.price,
currency: response.currency
});
// Update cart UI
updateCartDisplay(response);
}
});
}
</script>
<button to Cart</button>
Server-Side (Traditional Form Post)
In your controller:
using CMS.Ecommerce;
using Newtonsoft.Json;
public ActionResult AddToCart(int skuId, int quantity)
{
var sku = SKUInfoProvider.GetSKUInfo(skuId);
var cart = ECommerceContext.CurrentShoppingCart;
cart.AddItem(skuId, quantity);
cart.Evaluate();
// Prepare tracking data
ViewBag.AddToCartEvent = new
{
content_name = sku.SKUName,
content_ids = new[] { sku.SKUNumber },
content_type = "product",
value = sku.SKUPrice * quantity,
currency = cart.Currency.CurrencyCode
};
return View("Cart");
}
In your view:
@if (ViewBag.AddToCartEvent != null)
{
<script>
fbq('track', 'AddToCart', @Html.Raw(Json.Encode(ViewBag.AddToCartEvent)));
</script>
}
InitiateCheckout Event
Track when users begin checkout:
@using CMS.Ecommerce
@{
var cart = ECommerceContext.CurrentShoppingCart;
var contentIds = cart.CartItems.Select(item => item.SKU.SKUNumber).ToArray();
}
<script>
fbq('track', 'InitiateCheckout', {
content_category: 'checkout',
content_ids: [@Html.Raw(string.Join(",", contentIds.Select(id => $"'{id}'")))],
num_items: @cart.CartItems.Count,
value: @cart.TotalPrice,
currency: '@cart.Currency.CurrencyCode'
});
</script>
AddPaymentInfo Event
Track payment method selection:
<script>
function selectPaymentMethod(methodName) {
fbq('track', 'AddPaymentInfo', {
content_category: 'checkout',
value: @cart.TotalPrice,
currency: '@cart.Currency.CurrencyCode'
});
// Submit payment method
submitPaymentSelection(methodName);
}
</script>
<button Card</button>
<button
Purchase Event (Critical!)
Track completed transactions:
@using CMS.Ecommerce
@model OrderInfo
<script>
fbq('track', 'Purchase', {
value: @Model.OrderGrandTotal,
currency: '@Model.OrderCurrency.CurrencyCode',
content_ids: [@Html.Raw(string.Join(",", Model.OrderItems.Select(item => $"'{item.OrderItemSKU.SKUNumber}'")))],
content_type: 'product',
num_items: @Model.OrderItems.Sum(item => item.OrderItemUnitCount)
});
</script>
<h1>Thank You for Your Order!</h1>
<p>Order #@Model.OrderID</p>
Prevent Duplicate Purchase Tracking
@{
var purchaseTracked = SessionHelper.GetValue("MetaPixel_Purchase_" + Model.OrderID);
}
@if (purchaseTracked == null)
{
SessionHelper.SetValue("MetaPixel_Purchase_" + Model.OrderID, true);
<script>
fbq('track', 'Purchase', {
value: @Model.OrderGrandTotal,
currency: '@Model.OrderCurrency.CurrencyCode',
content_ids: [@Html.Raw(string.Join(",", Model.OrderItems.Select(item => $"'{item.OrderItemSKU.SKUNumber}'")))],
content_type: 'product'
});
</script>
}
Lead Event
Track lead generation (form submissions):
@if (ViewBag.FormSubmitted == true)
{
<script>
fbq('track', 'Lead', {
content_name: '@ViewBag.FormName',
content_category: 'lead_generation',
value: @ViewBag.LeadValue,
currency: 'USD'
});
</script>
}
Or with client-side tracking:
<script>
document.getElementById('leadForm').addEventListener('submit', function(e) {
fbq('track', 'Lead', {
content_name: 'contact_form',
content_category: 'lead_generation'
});
});
</script>
CompleteRegistration Event
Track user registrations:
@if (ViewBag.RegistrationComplete == true)
{
<script>
fbq('track', 'CompleteRegistration', {
content_name: 'user_registration',
status: 'completed',
value: 0,
currency: 'USD'
});
</script>
}
Contact Event
Track contact form submissions:
<script>
document.getElementById('contactForm').addEventListener('submit', function(e) {
fbq('track', 'Contact', {
content_name: 'contact_form',
content_category: 'customer_support'
});
});
</script>
Subscribe Event
Track newsletter signups:
<script>
document.getElementById('newsletterForm').addEventListener('submit', function(e) {
fbq('track', 'Subscribe', {
value: 0,
currency: 'USD',
predicted_ltv: 100
});
});
</script>
Custom Events
For actions not covered by standard events, use custom events:
<script>
// Track custom event
fbq('trackCustom', 'EventName', {
customParam1: 'value1',
customParam2: 'value2'
});
</script>
Example: Product Comparison
<script>
function trackProductComparison(productIds) {
fbq('trackCustom', 'CompareProducts', {
product_ids: productIds,
num_products: productIds.length
});
}
// Usage
trackProductComparison(['SKU123', 'SKU456', 'SKU789']);
</script>
Example: Video View
<script>
var video = document.getElementById('productVideo');
video.addEventListener('play', function() {
fbq('trackCustom', 'VideoView', {
video_title: this.getAttribute('data-title'),
product_id: '@Model.SKUNumber'
});
});
</script>
Example: Download Brochure
<script>
document.querySelectorAll('.brochure-download').forEach(function(link) {
link.addEventListener('click', function(e) {
fbq('trackCustom', 'DownloadBrochure', {
brochure_name: this.getAttribute('data-brochure-name'),
product_category: this.getAttribute('data-category')
});
});
});
</script>
Advanced E-commerce Tracking
Product Catalog Events
Track product listing page views:
@model IEnumerable<SKUInfo>
<script>
fbq('track', 'ViewContent', {
content_type: 'product_group',
content_category: '@ViewBag.CategoryName',
content_ids: [@Html.Raw(string.Join(",", Model.Select(p => $"'{p.SKUNumber}'")))],
contents: [
@foreach (var product in Model)
{
@:{
id: '@product.SKUNumber',
quantity: 1,
item_price: @product.SKUPrice
}@(product != Model.Last() ? "," : "")
}
]
});
</script>
Dynamic Product Ads (DPA) Format
For dynamic remarketing:
@model SKUInfo
<script>
fbq('track', 'ViewContent', {
content_type: 'product',
content_ids: ['@Model.SKUNumber'],
content_name: '@Model.SKUName',
content_category: '@(Model.PrimaryCategory?.CategoryDisplayName ?? "")',
value: @Model.SKUPrice,
currency: '@CurrencyInfoProvider.GetMainCurrency(SiteContext.CurrentSiteID).CurrencyCode',
contents: [{
id: '@Model.SKUNumber',
quantity: 1,
item_price: @Model.SKUPrice
}]
});
</script>
Remove from Cart
<script>
function removeFromCart(cartItemId, itemData) {
$.ajax({
url: '/ShoppingCart/RemoveItem',
method: 'POST',
data: { cartItemId: cartItemId },
success: function(response) {
fbq('trackCustom', 'RemoveFromCart', {
content_ids: [itemData.skuNumber],
content_name: itemData.skuName,
value: itemData.price * itemData.quantity,
currency: itemData.currency
});
}
});
}
</script>
Event Parameters Reference
Common Parameters
| Parameter | Type | Description |
|---|---|---|
value |
number | Monetary value of event |
currency |
string | Currency code (USD, EUR, etc.) |
content_name |
string | Name of content/product |
content_category |
string | Category of content |
content_ids |
array | Product/content IDs |
content_type |
string | Type: product, product_group |
contents |
array | Detailed product info |
num_items |
number | Number of items |
E-commerce Specific
| Parameter | Type | Description |
|---|---|---|
contents |
array | Array of product objects |
predicted_ltv |
number | Predicted lifetime value |
status |
string | Status of action |
Kentico-Specific Integrations
Track Page Type Views
@using CMS.DocumentEngine
@{
var currentDoc = DocumentContext.CurrentDocument;
}
<script>
fbq('trackCustom', 'PageTypeView', {
page_type: '@currentDoc.ClassName',
page_name: '@currentDoc.DocumentName',
page_id: '@currentDoc.DocumentID'
});
</script>
Track Content Downloads
@using CMS.MediaLibrary
<script>
document.querySelectorAll('.media-download').forEach(function(link) {
link.addEventListener('click', function(e) {
fbq('trackCustom', 'DownloadContent', {
content_name: this.getAttribute('data-file-name'),
content_type: this.getAttribute('data-file-type'),
source: 'media_library'
});
});
});
</script>
Track Form Builder Forms
@using CMS.OnlineForms
<script>
document.querySelectorAll('form[data-kentico-form]').forEach(function(form) {
form.addEventListener('submit', function(e) {
var formName = this.getAttribute('data-kentico-form');
fbq('track', 'Lead', {
content_name: formName,
content_category: 'kentico_form',
value: 0,
currency: 'USD'
});
});
});
</script>
GTM Implementation (Alternative)
If using Google Tag Manager:
Create Meta Pixel Event Tag
<script>
fbq('track', '{{Event Name}}', {
value: {{Event Value}},
currency: '{{Currency}}',
content_ids: [{{Content IDs}}]
});
</script>
Set up Variables:
- Event Name (Data Layer Variable)
- Event Value (Data Layer Variable)
- Currency (Data Layer Variable)
- Content IDs (Data Layer Variable)
Trigger: Custom Event from data layer
Data Layer Push in Kentico
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
'event': 'addToCart',
'ecommerce': {
'currencyCode': '@cart.Currency.CurrencyCode',
'add': {
'products': [{
'id': '@product.SKUNumber',
'name': '@product.SKUName',
'price': @product.SKUPrice,
'quantity': 1
}]
}
},
'fbPixelValue': @product.SKUPrice,
'fbPixelContentIds': ['@product.SKUNumber']
});
</script>
Testing Events
1. Meta Pixel Helper
- Install Chrome extension
- Navigate to your site
- Perform actions
- Check helper icon for events
- Verify parameters are correct
2. Facebook Events Manager
- Open Events Manager
- Click Test Events
- Enter your website URL
- Perform actions on site
- Watch events appear in real-time
- Verify parameters
3. Browser Console Logging
<script>
// Log all Meta Pixel events
(function() {
var originalFbq = window.fbq;
window.fbq = function() {
console.log('Meta Pixel Event:', arguments);
return originalFbq.apply(this, arguments);
};
})();
</script>
4. Network Tab Inspection
- Open DevTools → Network
- Filter by "facebook"
- Perform action
- Check for request to
facebook.com/tr - Verify event parameters in request
Event Deduplication
To prevent duplicate events across different tracking methods:
<script>
fbq('track', 'Purchase', {
value: @Model.OrderGrandTotal,
currency: '@Model.OrderCurrency.CurrencyCode',
content_ids: ['@Model.OrderID']
}, {
eventID: 'purchase_@Model.OrderID'
});
</script>
Use same eventID in Conversions API to deduplicate.
Common Issues
Events Not Tracking
Check:
- Meta Pixel base code loaded before event code
- Correct event name (case-sensitive)
- JavaScript errors in console
- Network requests in DevTools
Wrong Event Parameters
Debug:
- Use Meta Pixel Helper
- Check Events Manager for parameter values
- Verify data types (numbers vs strings)
- Ensure required parameters are included
Currency Issues
Fix:
@{
// Always use ISO 4217 currency codes
var currency = CurrencyInfoProvider.GetMainCurrency(SiteContext.CurrentSiteID).CurrencyCode;
}
<script>
fbq('track', 'Purchase', {
value: @Model.OrderGrandTotal,
currency: '@currency' // e.g., 'USD', 'EUR', 'GBP'
});
</script>
Best Practices
- Use Standard Events: Prefer standard events over custom for better optimization
- Include Value: Always include monetary value when applicable
- Product IDs: Use consistent SKU numbers as content_ids
- Test Thoroughly: Test all events before launching campaigns
- Deduplicate: Use eventID to prevent duplicate counting
- Privacy Compliance: Don't send PII in event parameters
- Consistent Currency: Use same currency across all events
- Monitor Regularly: Check Events Manager for data quality
Event Value Assignment
Assign values to non-purchase events for optimization:
<script>
// Lead form with estimated value
fbq('track', 'Lead', {
content_name: 'demo_request',
value: 50.00, // Estimated lead value
currency: 'USD',
predicted_ltv: 500.00 // Predicted lifetime value
});
</script>
Next Steps
- Set Up Conversions API for server-side tracking
- Create Custom Conversions
- Build Custom Audiences
- Optimize for Events
- Troubleshoot Tracking Issues