Status-Driven Purchase Conversions
Record Facebook (and other platforms') purchase conversions only when WooCommerce confirms the order is in a paid state, using the platform's Conversion API as the single source of truth.
When you need this recipe
WooCommerce orders fall into three broad outcomes after checkout:
- Order fails immediately. Customer never reaches the thank-you page. Nothing fires. No action needed.
- Order is paid immediately (most Stripe/PayPal-style integrations). Browser pixel fires on the thank-you page, CAPI fires on the paid-status transition, both share the same
event_id, Meta deduplicates them. This is the normal case. No action needed. - Order goes to
processingbut may still fail or never get paid (bank transfer, invoice, BNPL, manual review). The browser pixel fires on the thank-you page and records the conversion, even if the order is later cancelled or never paid.
This recipe addresses case 3.
The Pixel Manager's default behavior tracks everything that does not immediately fail because most checkouts fall into case 2 and waiting on a paid status hurts attribution and Meta's optimizer for the common case. Use this recipe only when case 3 is frequent enough in your store to distort the numbers.
What CAPI is and is not
The Conversions API was built for tracking reliability: it sends events from the server directly to Meta to survive ad blockers, browser privacy controls, and network filters that suppress the browser pixel. In the standard setup, CAPI runs alongside the browser pixel as a backup, and Meta deduplicates the two via event_id. This recipe repurposes CAPI as the only sender for purchase events to take advantage of its built-in status-driven trigger.
7-day limitation
Meta's Conversions API only accepts events with an event_time within the last 7 days. If an order sits in processing longer than 7 days before transitioning to a paid status, its conversion is permanently lost. This is a hard limit on Meta's side.
How the Pixel Manager handles purchase events by default
For Facebook, the Pixel Manager fires the purchase event from two places:
- Browser pixel - fires on the order received (thank-you) page, regardless of the order's payment status.
- Conversion API (CAPI) - registered on
woocommerce_payment_completeand on everywoocommerce_order_status_{paid_status}transition (paid statuses come fromwc_get_is_paid_statuses()). A meta-key guard on the order prevents double-fires across these hooks.
Both events share the same event_id (pmw_{order_id}), which is how Facebook deduplicates them.
This means CAPI is already status-driven: failed, cancelled, and other non-paid orders never reach Facebook through the server-side pipeline. The only thing that records non-paid orders as conversions is the browser pixel firing on the thank-you page.
Recipe
To record conversions strictly when the order reaches a paid state, do two things:
1. Enable Facebook CAPI
In the Pixel Manager settings, enable Facebook Conversion API. This is what makes CAPI the source that delivers the purchase event to Meta.
Enabling Facebook in the Pixel Manager also disables the tracking pixel from the Meta for WooCommerce plugin if it is installed. Catalog sync from Meta for WooCommerce is not affected.
2. Suppress the Facebook browser pixel for purchase events
Add a JavaScript filter that returns null for purchase events on the Facebook pixel. Returning null from a pmw_pixel_data_{pixel} filter blocks that pixel from firing for the matched event.
add_action('wp_head', function() {
?>
<script>
window._pmwq = window._pmwq || [];
window._pmwq.push(function() {
pmw.hooks.addFilter(
'pmw_pixel_data_facebook',
'my-store/status-driven-purchase',
function(pixelData, eventName) {
if (eventName === 'purchase') {
return null;
}
return pixelData;
}
);
});
</script>
<?php
}, 1);
With the browser purchase event suppressed, CAPI is the only sender, dedup is no longer relevant, and conversions appear in Meta when WooCommerce transitions the order into a paid state. For most payment gateways this is essentially immediate; for offline or manually approved payments, the conversion is recorded the moment the order moves into a paid status.
Optional: stricter "paid" definition (server-side filter)
The Pixel Manager already gates CAPI on wc_get_is_paid_statuses(), which by default includes processing and completed. If your store needs a narrower definition (for example: only completed, never processing), use the server-side filter for the Facebook purchase event.
The order ID is encoded in event_id as pmw_{order_id}. Parse it and load the order:
add_filter('pmw_server_event_payload_facebook_purchase', function($pixel_data, $pixel_name, $event_name) {
if (empty($pixel_data['event_id'])) {
return $pixel_data;
}
$order_id = (int) str_replace('pmw_', '', $pixel_data['event_id']);
$order = wc_get_order($order_id);
if (!$order) {
return $pixel_data;
}
// Custom rule: only completed orders count as paid.
if ($order->get_status() !== 'completed') {
return null;
}
return $pixel_data;
}, 10, 3);
Returning null from this filter blocks the CAPI event for the matched pixel and event.
Optional: manually re-fire CAPI for an order
If a custom workflow needs to push a CAPI purchase event for a specific order (for example from a custom hook), call the platform's static send_purchase_hit() method with the order object:
\SweetCode\Pixel_Manager\Pixels\Facebook\Facebook_CAPI::send_purchase_hit($order);
This is an internal method and is not part of the public Pixel Manager API. It can change between releases.
Same pattern for other platforms
The same approach works for every platform that has a server-side counterpart in the Pixel Manager. Replace the pixel slug in both filter names.
| Platform | JavaScript filter | PHP server-side filter |
|---|---|---|
| Facebook / Meta | pmw_pixel_data_facebook | pmw_server_event_payload_facebook_purchase |
| TikTok | pmw_pixel_data_tiktok | pmw_server_event_payload_tiktok_purchase |
pmw_pixel_data_pinterest | pmw_server_event_payload_pinterest_purchase | |
| Snapchat | pmw_pixel_data_snapchat | pmw_server_event_payload_snapchat_purchase |
pmw_pixel_data_reddit | pmw_server_event_payload_reddit_purchase | |
| Google Analytics 4 | pmw_pixel_data_google_analytics | pmw_server_event_payload_google_analytics_purchase |
Troubleshooting
- Conversions still appear for failed orders. The browser pixel filter is not active. Confirm the snippet is rendered in the page source and that
pmw.hooksis defined when it runs (this is what the_pmwqqueue guarantees). - No conversions appear at all. Confirm Facebook CAPI is enabled in the Pixel Manager settings and that the access token is valid. Check the Pixel Manager logs for the CAPI request.
- Conversions appear later than expected. That is the expected behavior. CAPI fires when WooCommerce transitions the order into a paid status, not when the customer lands on the thank-you page.