Event Filters
Version 1.51.0 of the Pixel Manager
Customize event tracking data for all pixels using JavaScript (front-end) and PHP (server-side) filters.
Why Use the Command Queue?
Always wrap your filters in the Pixel Manager command queue:
window._pmwq = window._pmwq || [];
window._pmwq.push(function() {
pmw.hooks.addFilter('pmw_pixel_data_facebook', 'my-plugin', function(pixelData) {
pixelData.custom_data.custom_field = 'my_value';
return pixelData;
});
});
Why? Caching systems and JavaScript optimizers may shuffle, combine, or delay script loading. The command queue provides a 100% reliable way to ensure your filters register after Pixel Manager loads, preventing race conditions and initialization errors. Without it, pmw.hooks may not exist yet, causing your code to fail silently.
Adding to WordPress:
add_action('wp_head', function() {
?>
<script>
window._pmwq = window._pmwq || [];
window._pmwq.push(function() {
pmw.hooks.addFilter('pmw_pixel_data_facebook', 'my-plugin', function(pixelData) {
pixelData.custom_data.custom_field = 'my_value';
return pixelData;
});
});
</script>
<?php
}, 1); // Priority 1 to load early in <head>
Planning Your Filters
Before implementing filters, consider where your events are processed:
Front-End vs. Server-Side Events
Front-end events (processed in the browser):
- All events when server-to-server tracking is disabled
- Events like
add_to_cart,view_item,begin_checkout, etc. - Purchase events only if processed through the browser
Server-side events (processed on the server):
- Purchase events when server-to-server tracking is enabled (Facebook CAPI, TikTok EAPI, Pinterest APIC, Snapchat CAPI)
- Google Analytics purchase events when Measurement Protocol is enabled
- These are always sent from the server, never through the browser
Why server-side purchase events? Browser-based tracking can be blocked by ad blockers, browser extensions, privacy settings, or network-level filters. When server-to-server tracking is enabled, purchase events are compiled and sent directly from your server to the advertising platforms, completely bypassing the browser. This makes them immune to client-side blocking, ensuring 100% reliable conversion tracking. The tradeoff is that these events are processed in a completely independent pipeline, which means they require separate filters.
When server-to-server tracking is active, purchase events are compiled and sent exclusively from the server. This means:
- Front-end filters will NOT affect these purchase events
- You must implement PHP server-side filters to modify purchase event data
Example: To filter purchase events with server-to-server tracking enabled, you need both:
// Front-end (for any browser-based purchase events)
window._pmwq.push(function() {
pmw.hooks.addFilter('pmw_event_payload_purchase', 'my-filter', function(payload) {
payload.event_data.custom_field = 'value';
return payload;
});
});
// Server-side (REQUIRED for server-to-server purchase events)
add_filter('pmw_server_event_payload_event_purchase', function($pixel_data, $pixel_name, $event_name) {
$pixel_data['custom_data']['custom_field'] = 'value';
return $pixel_data;
}, 10, 3);
Always implement server-side filters when working with purchase events if you have server-to-server tracking enabled.
Front-End Filters (JavaScript)
Filter Pipeline
Events flow through 4 stages. Each filter must return the modified data:
pmw_event_payload_pre- Before pixel transformations (modify core event data)pmw_pixel_data_{pixel}- Per-pixel transformations (e.g.,pmw_pixel_data_facebook)pmw_event_payload_{event}- Per-event type (e.g.,pmw_event_payload_purchase)pmw_event_payload_post- Final stage (logging, debugging)
Supported pixels: facebook, google_ads, google_analytics, tiktok, pinterest, snapchat, linkedin, microsoft_ads, twitter, reddit, taboola, outbrain
Supported events: page_view, add_to_cart, view_item, view_item_list, begin_checkout, add_payment_info, add_to_wishlist, search, purchase
API
pmw.hooks.addFilter(hookName, namespace, callback, priority)
pmw.hooks.removeFilter(hookName, namespace)
pmw.hooks.hasFilter(hookName, namespace)
- namespace - Unique identifier to prevent conflicts (e.g.,
'my-plugin/feature') - priority - Execution order (default: 10, lower runs first)
- Return
nullto block an event from firing
Examples
Add Custom Facebook Parameters
window._pmwq.push(function() {
pmw.hooks.addFilter('pmw_pixel_data_facebook', 'my-store', function(pixelData) {
pixelData.custom_data = pixelData.custom_data || {};
pixelData.custom_data.store_location = 'NYC';
pixelData.custom_data.user_segment = 'premium';
return pixelData;
});
});
Adjust Prices Globally
window._pmwq.push(function() {
pmw.hooks.addFilter('pmw_event_payload_pre', 'price-modifier', function(payload) {
if (payload.event_data?.product?.price) {
payload.event_data.product.price *= 1.15; // +15% markup
}
return payload;
});
});
Filter by Event Type
window._pmwq.push(function() {
pmw.hooks.addFilter('pmw_event_payload_purchase', 'purchase-tags', function(payload) {
if (payload.event_data?.order_total > 500) {
payload.event_data.high_value = true;
}
return payload;
});
});
Block Events Conditionally
window._pmwq.push(function() {
pmw.hooks.addFilter('pmw_pixel_data_facebook', 'admin-filter', function(pixelData) {
if (window.userIsAdmin) {
return null; // Block event
}
return pixelData;
});
});
Use Priority for Execution Order
window._pmwq.push(function() {
// Runs first (priority 5)
pmw.hooks.addFilter('pmw_event_payload_pre', 'early-filter', function(payload) {
payload.event_data.processed_by = ['early-filter'];
return payload;
}, 5);
// Runs second (priority 10)
pmw.hooks.addFilter('pmw_event_payload_pre', 'late-filter', function(payload) {
payload.event_data.processed_by.push('late-filter');
return payload;
}, 10);
});
Server-Side Filters (PHP)
Filter Pipeline
Server-side events (Facebook CAPI, TikTok EAPI, Pinterest APIC, Snapchat CAPI) flow through 5 stages:
pmw_server_event_payload_pre- Before pixel processing (all pixels at once)pmw_server_event_payload_{pixel}- Per-pixel, all events (e.g.,facebook)pmw_server_event_payload_event_{event}- Per-event, all pixels (e.g.,purchase)pmw_server_event_payload_{pixel}_{event}- Specific pixel + event (e.g.,facebook_purchase)pmw_server_event_payload_post- Final stage before API transmission
Examples
Modify All Purchase Events (All Pixels)
add_filter('pmw_server_event_payload_event_purchase', function($pixel_data, $pixel_name, $event_name) {
// Add timestamp to all purchase events across all pixels
$pixel_data['custom_data']['order_timestamp'] = time();
// Categorize by value
if (isset($pixel_data['custom_data']['value'])) {
$value = $pixel_data['custom_data']['value'];
$pixel_data['custom_data']['value_tier'] = $value < 50 ? 'low' : ($value < 200 ? 'medium' : 'high');
}
return $pixel_data;
}, 10, 3);
Add Custom Data to Facebook Only
add_filter('pmw_server_event_payload_facebook', function($pixel_data, $pixel_name) {
$pixel_data['user_data']['subscription_status'] = 'premium';
return $pixel_data;
}, 10, 2);
Target Specific Pixel + Event
add_filter('pmw_server_event_payload_facebook_purchase', function($pixel_data, $pixel_name, $event_name) {
$user_id = get_current_user_id();
if ($user_id) {
$ltv = get_user_meta($user_id, 'customer_ltv', true);
if ($ltv > 1000 && isset($pixel_data['custom_data']['value'])) {
$pixel_data['custom_data']['value'] *= 1.2; // Boost value for high-LTV customers
}
}
return $pixel_data;
}, 10, 3);
Block Events Conditionally
// Block low-value purchases from all pixels
add_filter('pmw_server_event_payload_event_purchase', function($pixel_data, $pixel_name, $event_name) {
if (isset($pixel_data['custom_data']['value']) && $pixel_data['custom_data']['value'] < 10) {
return null; // Blocks event for all pixels
}
return $pixel_data;
}, 10, 3);
// Block only from Facebook
add_filter('pmw_server_event_payload_facebook', function($pixel_data) {
if (some_condition()) {
return null;
}
return $pixel_data;
});
Event Payload Structure
{
event: 'add_to_cart',
event_data: {
product: {
id: 123,
name: 'Product Name',
price: 99.99,
quantity: 1,
currency: 'USD',
categories: ['Electronics']
}
},
pixels: {
facebook: {
event_name: 'AddToCart',
event_id: 'unique-id',
custom_data: { /* pixel-specific data */ }
},
google_analytics: {
event_name: 'add_to_cart',
event_data: { /* pixel-specific data */ }
}
}
}
Best Practices
- Always return the value - Filters must return the modified data or
nullto block - Use unique namespaces - Format:
'plugin-name/feature'or'company-name/modifier' - Wrap in
_pmwq- Ensures Pixel Manager loads before your filters - Check data exists - Use optional chaining:
payload.event_data?.product?.price - Use appropriate priority - Default is 10; lower numbers run first
- Test thoroughly - Check browser console for filter execution logs
Debugging
Console Logging
Filter execution is logged to the browser console:
🔍 Pre-processing filter called: add_to_cart
📊 GA pixel data filter called: add_to_cart
Inspect Payloads
window._pmwq.push(function() {
pmw.hooks.addFilter('pmw_event_payload_post', 'debugger', function(payload, eventName) {
console.log(`Event: ${eventName}`, payload);
return payload;
}, 999); // High priority to run last
});
PHP Debugging
add_filter('pmw_server_event_payload_post', function($pixel_data, $pixel_name) {
if (defined('WP_DEBUG') && WP_DEBUG) {
error_log("Sending {$pixel_data['event_name']} to {$pixel_name}: " . json_encode($pixel_data));
}
return $pixel_data;
}, 10, 2);
Migration from Old System
If you were using jQuery event listeners:
Before:
jQuery(document).on("pmw:add-to-cart", function(event, product) {
product.price = product.price * 1.1;
});
After:
window._pmwq.push(function() {
pmw.hooks.addFilter('pmw_event_payload_add_to_cart', 'namespace', function(payload) {
payload.event_data.product.price *= 1.1;
return payload;
});
});