Meta Pixel Event Tracking | OpsBlu Docs

Meta Pixel Event Tracking

How to implement Meta Pixel standard and custom events on OpenCart. Covers ecommerce events, lead tracking, event deduplication, and Conversions API.

Overview

Meta Pixel events track user interactions for:

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

  1. Install Meta Pixel Helper
  2. Visit your store
  3. Trigger events (add to cart, checkout, etc.)
  4. Check extension icon for event detection
  5. Click for detailed event parameters

Test Events Tool

Facebook Events Manager > [Your Pixel] > Test Events
  1. Enter website URL or use browser extension
  2. Perform actions on your site
  3. Events appear in real-time
  4. 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:

  1. Check fbq function is loaded: console.log(typeof fbq)
  2. Verify Pixel initialization before event tracking
  3. Check JavaScript console for errors
  4. Test with Pixel Helper extension
  5. Ensure ad blockers are disabled

Incorrect Parameters

Problem: Event fires but parameters are wrong

Solutions:

  1. Console.log variables before passing to fbq:
    console.log('Product ID:', productId);
    console.log('Price:', price);
    
  2. Verify data types (value should be number, not string)
  3. Check currency code is valid ISO 4217
  4. Ensure content_ids is an array

Duplicate Events

Problem: Same event fires multiple times

Solutions:

  1. Use .off() before .on() for event handlers
  2. Implement event deduplication with eventID
  3. Check for multiple tracking codes
  4. Verify event isn't in multiple theme files

Next Steps

Additional Resources