WooCommerce Event Tracking with Meta Pixel | OpsBlu Docs

WooCommerce Event Tracking with Meta Pixel

Advanced Meta Pixel event tracking for WooCommerce including custom events, dynamic ads, and Conversions API

Beyond standard eCommerce events, Meta Pixel offers custom event tracking, dynamic ads support, and advanced features to optimize Facebook and Instagram campaigns for WooCommerce stores.

Standard Meta Pixel Events for WooCommerce

Event When It Fires Use Case
PageView Every page load General site traffic
ViewContent Product page view Product interest, dynamic ads
AddToCart Product added to cart Cart abandonment, remarketing
AddToWishlist Product added to wishlist Interest signals
InitiateCheckout Checkout page loaded Purchase intent
AddPaymentInfo Payment method selected High purchase intent
Purchase Order completed Conversion tracking
Search Product search performed Search behavior analysis
Lead Form submission Lead generation tracking
Subscribe Subscription purchase Recurring revenue tracking

Advanced WooCommerce Event Tracking

1. Search Tracking

Track WooCommerce product searches:

// Track product search
add_action('pre_get_posts', 'meta_pixel_track_search');
function meta_pixel_track_search($query) {
    if (!is_admin() && $query->is_main_query() && $query->is_search()) {
        $search_term = $query->query_vars['s'];
        WC()->session->set('pixel_search_term', $search_term);
    }
}

add_action('woocommerce_before_shop_loop', 'meta_pixel_output_search');
function meta_pixel_output_search() {
    if (is_search()) {
        $search_term = WC()->session->get('pixel_search_term');
        if ($search_term) {
            global $wp_query;
            ?>
            <script>
                fbq('track', 'Search', {
                    search_string: '<?php echo esc_js($search_term); ?>',
                    content_category: 'product',
                    content_ids: [],
                    contents: []
                });
            </script>
            <?php
            WC()->session->__unset('pixel_search_term');
        }
    }
}

2. AddToWishlist Event

If using a wishlist plugin (YITH, WooCommerce Wishlists):

// Track add to wishlist (YITH Wishlist)
add_action('yith_wcwl_added_to_wishlist', 'meta_pixel_add_to_wishlist');
function meta_pixel_add_to_wishlist() {
    $product_id = isset($_POST['add_to_wishlist']) ? absint($_POST['add_to_wishlist']) : 0;
    if (!$product_id) return;

    $product = wc_get_product($product_id);
    ?>
    <script>
        fbq('track', 'AddToWishlist', {
            content_ids: ['<?php echo $product->get_sku() ? $product->get_sku() : $product->get_id(); ?>'],
            content_type: 'product',
            content_name: '<?php echo esc_js($product->get_name()); ?>',
            value: <?php echo (float) $product->get_price(); ?>,
            currency: '<?php echo get_woocommerce_currency(); ?>'
        });
    </script>
    <?php
}

// Alternative: Track via JavaScript
add_action('wp_footer', 'meta_pixel_wishlist_js');
function meta_pixel_wishlist_js() {
    if (!function_exists('YITH_WCWL')) return;
    ?>
    <script>
        jQuery(document).on('click', '.add_to_wishlist', function() {
            var productId = jQuery(this).data('product-id');
            var productName = jQuery(this).closest('.product').find('.woocommerce-loop-product__title').text();
            var price = parseFloat(jQuery(this).closest('.product').find('.price .amount').first().text().replace(/[^0-9.-]+/g, ''));

            fbq('track', 'AddToWishlist', {
                content_ids: [productId],
                content_type: 'product',
                content_name: productName,
                value: price,
                currency: '<?php echo get_woocommerce_currency(); ?>'
            });
        });
    </script>
    <?php
}

3. AddPaymentInfo Event

Track payment method selection:

// Track payment method selection on checkout
add_action('woocommerce_review_order_after_payment', 'meta_pixel_payment_method_js');
function meta_pixel_payment_method_js() {
    ?>
    <script>
        jQuery(document).ready(function($) {
            $('input[name="payment_method"]').on('change', function() {
                var paymentMethod = $(this).val();

                fbq('track', 'AddPaymentInfo', {
                    value: <?php echo WC()->cart ? WC()->cart->get_total('raw') : 0; ?>,
                    currency: '<?php echo get_woocommerce_currency(); ?>',
                    content_category: 'checkout',
                    payment_method: paymentMethod
                });
            });
        });
    </script>
    <?php
}

4. Contact Form Submissions (Lead)

Track contact form submissions as leads:

// Track Contact Form 7 submissions
add_action('wpcf7_mail_sent', 'meta_pixel_contact_form_lead');
function meta_pixel_contact_form_lead($contact_form) {
    ?>
    <script>
        fbq('track', 'Lead', {
            content_name: '<?php echo esc_js($contact_form->title()); ?>',
            content_category: 'contact_form'
        });
    </script>
    <?php
}

// Track Gravity Forms submissions
add_action('gform_after_submission', 'meta_pixel_gravity_form_lead', 10, 2);
function meta_pixel_gravity_form_lead($entry, $form) {
    ?>
    <script>
        fbq('track', 'Lead', {
            content_name: '<?php echo esc_js($form['title']); ?>',
            content_category: 'gravity_form'
        });
    </script>
    <?php
}

5. CompleteRegistration Event

Track new customer registrations:

// Track customer registration
add_action('woocommerce_created_customer', 'meta_pixel_registration', 10, 1);
function meta_pixel_registration($customer_id) {
    ?>
    <script>
        fbq('track', 'CompleteRegistration', {
            content_name: 'customer_registration',
            status: 'completed'
        });
    </script>
    <?php
}

6. Custom Events for Specific User Actions

// Track quick view (if theme supports)
add_action('wp_footer', 'meta_pixel_quick_view');
function meta_pixel_quick_view() {
    if (!is_shop() && !is_product_category()) return;
    ?>
    <script>
        jQuery(document).on('click', '.quick-view-button', function() {
            var productId = jQuery(this).data('product-id');
            var productName = jQuery(this).closest('.product').find('.woocommerce-loop-product__title').text();

            fbq('trackCustom', 'QuickView', {
                content_ids: [productId],
                content_name: productName,
                content_type: 'product'
            });
        });
    </script>
    <?php
}

// Track product reviews
add_action('comment_post', 'meta_pixel_product_review', 10, 3);
function meta_pixel_product_review($comment_id, $approved, $commentdata) {
    if ($approved && get_post_type($commentdata['comment_post_ID']) === 'product') {
        $product = wc_get_product($commentdata['comment_post_ID']);
        $rating = get_comment_meta($comment_id, 'rating', true);
        ?>
        <script>
            fbq('trackCustom', 'ProductReview', {
                content_ids: ['<?php echo $product->get_sku() ? $product->get_sku() : $product->get_id(); ?>'],
                content_name: '<?php echo esc_js($product->get_name()); ?>',
                rating: <?php echo $rating ? $rating : 0; ?>
            });
        </script>
        <?php
    }
}

WooCommerce Subscriptions Tracking

Track Subscription Events

// Track new subscription purchase
add_action('woocommerce_checkout_subscription_created', 'meta_pixel_subscription_purchase', 10, 3);
function meta_pixel_subscription_purchase($subscription, $order, $recurring_cart) {
    ?>
    <script>
        fbq('track', 'Subscribe', {
            value: <?php echo $subscription->get_total(); ?>,
            currency: '<?php echo $subscription->get_currency(); ?>',
            predicted_ltv: <?php echo $subscription->get_total() * 12; ?>,
            subscription_id: '<?php echo $subscription->get_id(); ?>'
        });
    </script>
    <?php
}

// Track subscription cancellation
add_action('woocommerce_subscription_status_cancelled', 'meta_pixel_subscription_cancel', 10, 1);
function meta_pixel_subscription_cancel($subscription) {
    ?>
    <script>
        fbq('trackCustom', 'CancelSubscription', {
            subscription_id: '<?php echo $subscription->get_id(); ?>',
            value: <?php echo $subscription->get_total(); ?>,
            currency: '<?php echo $subscription->get_currency(); ?>'
        });
    </script>
    <?php
}

// Track subscription renewal
add_action('woocommerce_subscription_renewal_payment_complete', 'meta_pixel_subscription_renewal', 10, 2);
function meta_pixel_subscription_renewal($subscription, $order) {
    ?>
    <script>
        fbq('trackCustom', 'SubscriptionRenewal', {
            subscription_id: '<?php echo $subscription->get_id(); ?>',
            order_id: '<?php echo $order->get_id(); ?>',
            value: <?php echo $order->get_total(); ?>,
            currency: '<?php echo $order->get_currency(); ?>'
        });
    </script>
    <?php
}

Dynamic Ads Product Catalog

Automatic Product Feed

The official "Facebook for WooCommerce" plugin automatically syncs your product catalog. For manual implementation:

// Generate product catalog feed
add_action('init', 'meta_product_catalog_feed');
function meta_product_catalog_feed() {
    if (isset($_GET['meta_catalog_feed'])) {
        header('Content-Type: text/xml; charset=UTF-8');

        $products = wc_get_products(array(
            'status' => 'publish',
            'limit' => -1
        ));

        echo '<?xml version="1.0" encoding="UTF-8"?>';
        echo '<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">';
        echo '<channel>';
        echo '<title>' . get_bloginfo('name') . '</title>';
        echo '<link>' . home_url() . '</link>';

        foreach ($products as $product) {
            echo '<item>';
            echo '<g:id>' . ($product->get_sku() ? $product->get_sku() : $product->get_id()) . '</g:id>';
            echo '<g:title><![CDATA[' . $product->get_name() . ']]></g:title>';
            echo '<g:description><![CDATA[' . wp_strip_all_tags($product->get_description()) . ']]></g:description>';
            echo '<g:link>' . $product->get_permalink() . '</g:link>';
            echo '<g:image_link>' . wp_get_attachment_url($product->get_image_id()) . '</g:image_link>';
            echo '<g:condition>new</g:condition>';
            echo '<g:availability>' . ($product->is_in_stock() ? 'in stock' : 'out of stock') . '</g:availability>';
            echo '<g:price>' . $product->get_price() . ' ' . get_woocommerce_currency() . '</g:price>';
            echo '<g:brand>' . get_product_brand($product) . '</g:brand>';

            $categories = get_the_terms($product->get_id(), 'product_cat');
            if ($categories && !is_wp_error($categories)) {
                echo '<g:product_type>' . $categories[0]->name . '</g:product_type>';
            }

            echo '</item>';
        }

        echo '</channel>';
        echo '</rss>';
        exit;
    }
}

function get_product_brand($product) {
    $brands = get_the_terms($product->get_id(), 'product_brand');
    return ($brands && !is_wp_error($brands)) ? $brands[0]->name : '';
}

// Access feed at: yoursite.com/?meta_catalog_feed=1

Enhanced Product Data for Dynamic Ads

// Add enhanced product data for better dynamic ads
add_action('woocommerce_after_single_product', 'meta_pixel_enhanced_product_data');
function meta_pixel_enhanced_product_data() {
    global $product;
    if (!$product) return;

    $categories = get_the_terms($product->get_id(), 'product_cat');
    $category_names = array();
    if ($categories && !is_wp_error($categories)) {
        foreach ($categories as $cat) {
            $category_names[] = $cat->name;
        }
    }

    $product_data = array(
        'content_ids' => array($product->get_sku() ? $product->get_sku() : $product->get_id()),
        'content_type' => 'product',
        'content_name' => $product->get_name(),
        'content_category' => implode(', ', $category_names),
        'value' => (float) $product->get_price(),
        'currency' => get_woocommerce_currency()
    );

    // Add availability
    if ($product->is_in_stock()) {
        $product_data['availability'] = 'in stock';
    } else {
        $product_data['availability'] = 'out of stock';
    }

    // Add condition
    $product_data['condition'] = 'new';

    // Add brand if available
    $brand = get_product_brand($product);
    if ($brand) {
        $product_data['brand'] = $brand;
    }
    ?>
    <script>
        fbq('track', 'ViewContent', <?php echo json_encode($product_data); ?>);
    </script>
    <?php
}

Meta Conversions API (Server-Side Events)

Server-Side Purchase Tracking

// Send server-side purchase event to Conversions API
add_action('woocommerce_thankyou', 'meta_capi_purchase_event', 20, 1);
function meta_capi_purchase_event($order_id) {
    if (!$order_id) return;

    // Skip if already tracked server-side
    if (get_post_meta($order_id, '_meta_capi_tracked', true)) {
        return;
    }

    $order = wc_get_order($order_id);

    // Build user data (hashed for privacy)
    $user_data = array(
        'em' => array(hash('sha256', strtolower(trim($order->get_billing_email())))),
        'ph' => array(hash('sha256', preg_replace('/[^0-9]/', '', $order->get_billing_phone()))),
        'fn' => array(hash('sha256', strtolower(trim($order->get_billing_first_name())))),
        'ln' => array(hash('sha256', strtolower(trim($order->get_billing_last_name())))),
        'ct' => array(hash('sha256', strtolower(trim($order->get_billing_city())))),
        'st' => array(hash('sha256', strtolower(trim($order->get_billing_state())))),
        'zp' => array(hash('sha256', trim($order->get_billing_postcode()))),
        'country' => array(hash('sha256', strtolower(trim($order->get_billing_country())))),
        'client_ip_address' => $_SERVER['REMOTE_ADDR'],
        'client_user_agent' => $_SERVER['HTTP_USER_AGENT']
    );

    // Build product data
    $content_ids = array();
    $contents = array();

    foreach ($order->get_items() as $item) {
        $product = $item->get_product();
        $product_id = $product->get_sku() ? $product->get_sku() : $product->get_id();

        $content_ids[] = $product_id;
        $contents[] = array(
            'id' => $product_id,
            'quantity' => $item->get_quantity(),
            'item_price' => (float) ($item->get_total() / $item->get_quantity())
        );
    }

    // Build event data
    $custom_data = array(
        'content_ids' => $content_ids,
        'contents' => $contents,
        'content_type' => 'product',
        'value' => (float) $order->get_total(),
        'currency' => $order->get_currency(),
        'num_items' => $order->get_item_count()
    );

    // Send to Conversions API
    send_meta_conversions_api_event('Purchase', $user_data, $custom_data);

    update_post_meta($order_id, '_meta_capi_tracked', true);
}

function send_meta_conversions_api_event($event_name, $user_data, $custom_data) {
    $pixel_id = 'YOUR_PIXEL_ID';
    $access_token = 'YOUR_ACCESS_TOKEN'; // From Events Manager → Settings → Conversions API

    $api_url = "https://graph.facebook.com/v18.0/{$pixel_id}/events";

    $event = array(
        'event_name' => $event_name,
        'event_time' => time(),
        'action_source' => 'website',
        'event_source_url' => home_url($_SERVER['REQUEST_URI']),
        'user_data' => $user_data,
        'custom_data' => $custom_data
    );

    // Add Facebook browser ID if available (fbp cookie)
    if (isset($_COOKIE['_fbp'])) {
        $event['user_data']['fbp'] = array($_COOKIE['_fbp']);
    }

    // Add Facebook click ID if available (fbc cookie)
    if (isset($_COOKIE['_fbc'])) {
        $event['user_data']['fbc'] = array($_COOKIE['_fbc']);
    }

    $body = array(
        'data' => array($event),
        'access_token' => $access_token
    );

    $response = wp_remote_post($api_url, array(
        'body' => json_encode($body),
        'headers' => array('Content-Type' => 'application/json'),
        'timeout' => 10
    ));

    // Log errors for debugging
    if (is_wp_error($response)) {
        error_log('Meta CAPI Error: ' . $response->get_error_message());
    }
}

Event Deduplication

Prevent duplicate events from browser and server-side tracking:

// Add event_id to both browser and server-side events
add_action('woocommerce_thankyou', 'meta_pixel_purchase_with_dedup', 10, 1);
function meta_pixel_purchase_with_dedup($order_id) {
    if (!$order_id) return;

    $event_id = 'order_' . $order_id . '_' . time();

    // Browser-side event with event_id
    ?>
    <script>
        fbq('track', 'Purchase', {
            // ... purchase data
        }, {
            eventID: '<?php echo $event_id; ?>'
        });
    </script>
    <?php

    // Send same event_id to Conversions API
    // (modify send_meta_conversions_api_event to accept event_id parameter)
}

Testing Meta Pixel Events

1. Meta Pixel Helper

  • Install Chrome extension
  • Visit WooCommerce store
  • Verify all events fire with correct parameters

2. Events Manager Test Events

  1. Go to Meta Events Manager
  2. Select your Pixel
  3. Click Test Events tab
  4. Enter your website URL
  5. Perform actions and verify events appear

3. Check Event Match Quality

In Events Manager:

  • View Event Match Quality score
  • Ensure advanced matching parameters sent
  • Aim for score > 6.0 for optimal performance

Best Practices

  1. Use Advanced Matching - Send hashed user data for better attribution
  2. Implement Conversions API - Improve iOS 14.5+ tracking
  3. Deduplicate Events - Use event_id for browser + server events
  4. Track Full Funnel - ViewContent → AddToCart → InitiateCheckout → Purchase
  5. Use Standard Events - Prefer standard events over custom events
  6. Include Product IDs - Use SKUs for product catalog matching
  7. Test Thoroughly - Verify all events before launching campaigns

Next Steps