Skip to main content

PHP Filters

While our goal is to make the plugin very simple to use through the user interface, this can be limiting for users and developers who need much more granular control over the plugin's output. For those users we provide filters that give them the option to adjust the plugin's behavior programmatically, making the options almost limitless.

Filters can be added to the functions.php file in your child-theme or by using them in a custom plugin. The easiest and safest way is using them in the functions.php file: functions.php

If you think there is a good use case for a new filter, let us know by sending a feature request here.

The $order argument

Every filter on this page that carries an order passes you the WooCommerce order, a WC_Order, whether the value is being calculated for the browser event on the order confirmation page or for a server-side event at the end of the checkout request. Type-hinting it or checking instanceof WC_Order is safe.

On versions 1.65.0 to 1.67.0 this did not hold for the server-side path, which handed the filters the plugin's own internal order object instead. A callback that type-hints WC_Order ended the checkout request in a fatal error there, and one that checks instanceof WC_Order silently did nothing at all. Fixed in 1.67.1. If you wrote a workaround for it, it can go: resolving the order through get_native_order() is no longer needed.

Marketing Conversion Value Filter

Use the marketing conversion value filter in order to recalculate the conversion value. The output will only affect the conversion value of the paid ads pixels (marketing pixels). The Google Analytics conversion value output will not be touched.

add_filter( 'pmw_marketing_conversion_value_filter', 'filter_conversion_value', 10, 2 );

Example:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_marketing_conversion_value_filter', function ($order_total, $order) {
/**
* The order total is the value that is being output as configured
* within the plugin. If you wish to override this and calculate
* the value from scratch, the filter also provides the order object
* with the raw order values.
*
* Example: The average cost to prepare an order for shipping is
* 10% of the order value. Therefore we remove 10% of the order value on
* each order.
**/

return $order_total * 0.9;
}, 10, 2);

Analytics Order Value Filters

The marketing conversion value filter deliberately leaves the analytics value alone. These two filters are its counterpart. They change the order value that goes to the analytics side of the reporting, without touching what the paid ads pixels report.

info

Available since version 1.43.4.

pmw_order_value_total_statistics filters the order total. It is the value that reaches:

  • the Google Analytics purchase event, both the browser event and the server-side Measurement Protocol event
  • the Google Analytics refund events, whose amount is derived from it
  • pmwDataLayer.order.value.total, and with it the purchase revenue of Microsoft Clarity, Contentsquare, GroundTruth and VWO
/wp-content/themes/child-theme/functions.php
add_filter('pmw_order_value_total_statistics', function ($order_total, $order) {

/**
* Report the order without shipping, so the revenue in Google Analytics
* matches the merchandise revenue in the bookkeeping.
**/

return $order_total - (float) $order->get_shipping_total();
}, 10, 2);

pmw_order_value_subtotal_statistics filters $order->get_subtotal(), which is the sum of the line items without shipping, fees or tax. It ends up in pmwDataLayer.order.value.subtotal. No pixel reads that key. It is there for your own code and for the event filters.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_order_value_subtotal_statistics', function ($order_subtotal, $order) {
return $order_subtotal;
}, 10, 2);
warning

Both filters are applied before the value is rounded to two decimals. Return a number, not a formatted string.

Additional Google Ads Conversion Pixels

info

This filter will only work if the main Conversion ID and Conversion Label are set in the Pixel Manager under Tracking Pixels → Google (Ads & GA4) (which activates the Google Ads conversion tracking in the first place).

With the following filter the Pixel Manager provides a way to add more than one Google Ads conversion pixel programmatically.

This filter will add additional conversion ID and label pairs to the output of the Google Ads pixel.

It will add the output to every page with the Google Ads remarketing pixel, including the purchase confirmation page.

Place the following code into your functions.php and replace the placeholders.

There are two examples below. The first and more common one shows how to add single conversion ID and label pairs. This is when you use different Google Ads accounts to run campaigns for the same website. The second example shows how to add multiple conversion labels for the same conversion ID. This is useful if you want to track different purchase conversion actions in the same Google Ads account. That is if you use one Google Ads account and run campaigns for different websites and want a separate conversion action for each website.

Here's an example that adds single conversion ID and label pairs:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_google_ads_conversion_identifiers', function ($conversion_identifiers) {

$conversion_identifiers['CONVERSION_ID_2'] = 'CONVERSION_LABEL_2';
$conversion_identifiers['CONVERSION_ID_3'] = 'CONVERSION_LABEL_3';
return $conversion_identifiers;
});

Here's an example that adds multiple conversion labels for the same conversion ID:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_google_ads_conversion_identifiers', function ( $conversion_identifiers ) {

// Add multiple conversion labels for the same conversion ID
$conversion_identifiers['CONVERSION_ID_1'] = [
$conversion_identifiers['CONVERSION_ID_1'], // add the existing label, otherwise it will be removed
'CONVERSION_LABEL_2',
'CONVERSION_LABEL_3',
];

return $conversion_identifiers;
});

Additional Facebook Pixels

info

This filter requires Pixel Manager 1.64.0 or higher, and it will only work if the main Pixel ID is set in the Pixel Manager under Tracking Pixels → Facebook (Meta) (which activates the Facebook pixel in the first place).

With the following filter the Pixel Manager provides a way to add more than one Facebook (Meta) pixel programmatically.

Every event, on every page, is sent to all configured pixels. This is useful if you want to track the same shop in more than one Facebook ad account or dataset.

tip

Before you add a second pixel, check whether sharing your existing pixel with the other ad account solves your case. A single data source keeps all conversions, audiences and learnings together and remains Meta's own best practice. More on that trade-off in the FAQ.

The filter receives an array that is already seeded with the pixel from the settings, including its Conversion API token and test event code. Append your additional pixels to it and return the array.

Each pixel is an array with the following keys:

  • pixel_id (required): The Facebook pixel ID. It has to be numeric. Entries without a valid pixel ID are ignored, and a pixel ID that appears more than once is only used once.
  • capi_token (optional, Pro): A Conversion API access token for this pixel. If set, all server-side events, including purchases, the generic server-side events and the subscription lifecycle events, are also sent to this pixel. If omitted, the pixel only receives browser events.
  • test_event_code (optional, Pro): A Conversion API test event code for this pixel. Each pixel is tested with its own code.

Place the following code into your functions.php and replace the placeholders.

Here's an example that adds a second pixel with browser events only:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_facebook_pixel_identifiers', function ( $pixel_identifiers ) {

$pixel_identifiers[] = [
'pixel_id' => 'PIXEL_ID_2',
];

return $pixel_identifiers;
});

Here's an example that adds a second pixel including the Conversion API (Pro):

/wp-content/themes/child-theme/functions.php
add_filter('pmw_facebook_pixel_identifiers', function ( $pixel_identifiers ) {

$pixel_identifiers[] = [
'pixel_id' => 'PIXEL_ID_2',
'capi_token' => 'CAPI_TOKEN_2',
'test_event_code' => 'TEST_EVENT_CODE_2', // optional
];

return $pixel_identifiers;
});
note

Browser and Conversion API events share the same event ID per event, and Facebook deduplicates them per pixel, so each pixel receives every event exactly once.

If you are using the server-side proxy, the Pixel Manager automatically syncs the additional pixels to the proxy. After adding or changing pixels in the filter, the new configuration is picked up within a few minutes. To push it right away, open the Pixel Manager settings under Server-Side → SweetCode Server-Side Proxy and click Sync Now.

Verify that the additional pixels are tracking

  1. Open any page of your shop and check the data layer in the browser console. pmwDataLayer.pixels.facebook.pixel_ids lists every pixel the browser initializes. Access tokens are never part of the data layer, they stay on the server.
  2. Run fbq.getState().pixels in the browser console. It shows one entry per initialized pixel.
  3. Watch the network tab for requests to facebook.com/tr. Each event produces one request per pixel, all with the same eid (event ID) so Meta can deduplicate against the server-side events.
  4. For the Conversion API, use Meta's Test Events tool in each pixel's own Events Manager view, with that pixel's test_event_code.
  5. The debug info in the Pixel Manager lists all configured pixels in the Meta sections, including the Meta Event Setup Tool and Meta Business Category Event Restrictions checks.
caution

Do not make the filter output depend on the current page, the current product or the logged-in user. Server-side events run in contexts that have nothing to do with the page the visitor was on, for example a purchase triggered by a WooCommerce order hook or a subscription renewal, so a conditional filter can result in a pixel that receives the browser event but not the matching server-side event. Return the same set of pixels on every request.

Every additional pixel multiplies the number of requests to Meta, in the browser and, if it carries a Conversion API token, also on your server. Only add the pixels you really need.

More about how the multi-pixel output behaves, including advanced matching, consent and the mobile bridge: Multiple Meta (Facebook) pixels.

Premium feature

This filter only applies when the Google Ads Conversion Adjustments feature is active. It requires Pixel Manager 1.66.1 or newer. Earlier versions answer every request with 401 invalid_username once the filter is registered, because WordPress reads the credentials as an Application Password login before the Pixel Manager can check them.

The Pixel Manager exposes a public CSV feed at /wp-json/pmw/v1/google-ads/conversion-adjustments.csv that Google Ads fetches on the schedule you set up under Goals → Conversions → Uploads → Schedules. The feed contains recent cancelled and refunded order data (order ID, adjustment time, value, currency).

By default the URL is reachable without authentication. Google's scheduled upload treats the username and password as optional, so most shops never need this filter. If you want to lock the feed down so a competitor or scraper cannot harvest your refund data, register the pmw_google_ads_conversion_adjustments_credentials filter to require HTTP Basic Auth.

The filter must return an array with user and pass keys. When credentials are returned, the feed responds with 401 Unauthorized for any request that does not present matching Authorization: Basic credentials. The feed is also rate-limited to 30 requests per minute per IP regardless of whether the filter is active.

The credentials are feed credentials only. They are not a WordPress user, and you do not create a WordPress or WooCommerce account for them. Pick any username and a long random password.

Add the snippet to your functions.php:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_google_ads_conversion_adjustments_credentials', function () {
return [
'user' => 'gads-feed',
'pass' => 'paste-a-long-random-string-here',
];
});

Then, in Google Ads:

  1. Go to Goals → Conversions → Uploads → Schedules.
  2. Edit the existing conversion-adjustments.csv schedule (or create a new one).
  3. Paste the same user value into the Username (optional) field and the same pass value into the Password (optional) field.
  4. Click Save & Preview to confirm Google Ads can reach the feed.
Do not connect the feed through Data Manager

Google Ads Data Manager also offers an HTTPS data source, and that form makes the username and password mandatory. Data Manager cannot import conversion adjustments from a file, though: its conversion import has no adjustment type or adjusted value fields, so the feed cannot be mapped there. Use the Uploads → Schedules page for this feed. See Set up conversion adjustments.

Hosting compatibility

A small number of hosts running PHP under FastCGI strip the Authorization header before PHP sees it. If Google Ads reports authentication failures after enabling the filter, ask your host to forward the Authorization header to PHP, or add this rule to your site's .htaccess:

RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
Generating a strong password

Use a password manager or run openssl rand -base64 32 to generate a long random string. The longer the password, the safer the feed.

Adjust Google Analytics Config Parameters

To keep the user interface lightweight we only included basic parameters like Enhanced Link Attribution. For those who need much more granular control over the Google Analytics config parameters, we provide a filter. The filter can also be used to override parameters from the user interface.

info

GA4 processes IPs from pageviews anonymized by design. This can't be changed. IP Anonymization in Google Analytics For Universal Analytics we've set the default parameters to also anonymize IPs. That setting can be overwritten with the filter below.

The following code will remove the anonymize_ip parameter on all Google Universal Analytics configs:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_ga_ua_parameters', function ($analytics_parameters, $analytics_id) {

unset($analytics_parameters['anonymize_ip']);
return $analytics_parameters;
}, 10,2);

The following code will adjust the parameters only for the given Google Universal Analytics property:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_ga_ua_parameters', function ($analytics_parameters, $analytics_id) {

if('UA-12345678-3' == $analytics_id){

unset($analytics_parameters['anonymize_ip']);

/**
* The following parameter setting will override the one set
* in the user interface.
**/
$analytics_parameters['link_attribution'] = true;
}

return $analytics_parameters;
}, 10,2);

Or maybe, you want to set much more specific settings for link_attribution in your Google Universal Analytics property, like specified here:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_ga_ua_parameters', function ($analytics_parameters, $analytics_id) {

if('UA-12345678-3' == $analytics_id){

$analytics_parameters['link_attribution'] = [
'cookie_name' => '_gaela',
'cookie_expires' => 60,
'levels' => 2
];
}

return $analytics_parameters;
}, 10,2);

And with the following filter you can enable the debug mode in GA4.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_ga_4_parameters', function ($analytics_parameters, $analytics_id) {

$analytics_parameters['debug_mode'] = true;

return $analytics_parameters;
}, 10,2);

Product ID Output Filter for Paid Ads Pixels

To keep the UX simple and the setup consistent over several advertising channels, there is only one setting in the UX to adjust the product ID output. The same ID then will be used for all paid ads pixels. The standard setting is either the post ID (e.g. 14), the ID for the WooCommerce Google Feed plugin (e.g. woocommerce_gpf_14) or the SKU (e.g. Hoodie). In some cases you might need to use a different ID type on different channels. Maybe you're using the post ID for Google Ads, and the SKU for Meta (Facebook). In this case the following filter will adjust the output for a specific pixel. It is even possible to completely customize the ID, if necessary.

info

We strongly recommend using the post ID for all product catalogs and for the product ID output. It is the most compatible way and causes the least trouble.

Set specific product ID types per channel

By adding the pixel name to the filter name, you can choose which pixel you want to adjust. For Meta (Facebook) use pmw_product_id_type_for_facebook, for Microsoft Ads (Bing) use pmw_product_id_type_for_bing, etc. You can use the following pixel filters:

  • adroll
  • bing (for the Microsoft Ads pixel)
  • facebook (for the Meta pixel)
  • google_ads
  • linkedin
  • outbrain
  • pinterest
  • reddit
  • snapchat
  • taboola
  • tiktok
  • twitter

The default values are post_id for the post ID, gpf for the WooCommerce Google Feed ID output (e.g. woocommerce_gpf_14), and sku for the SKU.

Here's an example on how to switch the product ID output for Meta (Facebook) to the SKU:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_product_id_type_for_facebook', function () {
return 'sku';
});

Here's an example to switch the Meta (Facebook) output to post ID:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_product_id_type_for_facebook', function () {
return 'post_id';
});

Custom product IDs

You have even the option to completely customize the product ID output and assign it to a specific channel with the pmw_product_ids filter.

In the following example use the pmw_product_ids filter to add one or more custom IDs for each product. In a second step, use the pmw_product_id_type_for_ filter to assign the new custom ID to one or more specific pixels.

  1. The following filter creates the custom product IDs.
/wp-content/themes/child-theme/functions.php
add_filter('pmw_product_ids', function ($product_ids, $product) {
$product_ids['custom1'] = 'custom_type_' . $product->get_id();
$product_ids['custom2'] = 'custom_pinterest_catalog_' . $product->get_sku();

return $product_ids;
}, 10, 2);
  1. Then assign the new custom product IDs to the channels of your choice.
/wp-content/themes/child-theme/functions.php
add_filter('pmw_product_id_type_for_google_ads', function () {
return 'custom1';
});
/wp-content/themes/child-theme/functions.php
add_filter('pmw_product_id_type_for_pinterest', function () {
return 'custom2';
});

Google Analytics Product ID Output Filter

By default, the plugin uses the post ID as the identifier for Google Analytics. This filter allows you to change this to the SKU.

info

The main reasons why the plugin uses the post ID by default are:

  1. The post ID is more reliable. A shop owner might not add SKUs to all products, leaving the field sometimes empty. But we need to send an identifier to Google Analytics. (In the case the shop owner doesn't add a SKU to a product, we will fall back to the post ID.)
  2. The products can be identified by the product name in Google Analytics anyway.
  3. It is easier to search for a product ID in WooCommerce or in Google Analytics, so it's also more practical to use the post ID.
  4. Some Google tools (e.g. Google Ads scripts) return product IDs in lowercase only, even if they were uploaded with mixed or uppercase characters. Since the post ID is purely numerical, it is unaffected by case-sensitivity issues.
/wp-content/themes/child-theme/functions.php
add_filter('pmw_product_id_type_for_google_analytics', function () {
return 'sku';
});

View Item List Trigger Filter

The plugin uses a smart trigger for the view_item_list event. It only triggers if a product is actually visible in the viewport for more than 1 second. If a visitor scrolls up and down and sees a product several times, view_item_list will be triggered each time (again, only if visible for more than one second). The following filter allows tweaking that behavior.

Lazy loading products is supported too 😀

info

This will only work on a website where caching is off, or after flushing the cache each time you change the settings.

The following settings are available:

  • testMode: It activates the test mode, which shows a transparent overlay on each product for which view_item_list has been triggered.
  • backgroundColor: Change the background color of the test overlay in case product images are in use where the overlay would not be visible. This is only relevant for the test mode.
  • opacity: By default, the overlay is half transparent. Adjust the opacity to a level that suits better. This is only relevant for the test mode.
  • repeat: By default, the plugin resends view_item_list events when a visitor scrolls up and down and sees a product multiple times. Turn this off by setting the value to false. Then the plugin will send only one view_item_list event when a product becomes visible on a page.
  • threshold: This sets how much of a product card must be visible before the event is triggered. With a setting of 1 the event triggers only when 100% of the product is visible. The default is 0.8.
  • timeout: This value instructs the plugin how long a product must be visible before the view_item_list event is triggered. The timer resets each time the product leaves the viewport. The time must be set in milliseconds, and the default value is 1000 milliseconds (1 second).
/wp-content/themes/child-theme/functions.php
add_filter('pmw_view_item_list_trigger_settings', function ($settings) {

$settings['testMode'] = true;
$settings['backgroundColor'] = 'green';
// $settings['backgroundColor'] = 'rgba(60,179,113)';
$settings['opacity'] = 0.5;
$settings['repeat'] = true;
$settings['threshold'] = 0.8;
$settings['timeout'] = 1000;

return $settings;
});

Another simple way to enable the view_item_list demo mode is by appending the parameter vildemomode to the URL you want to test. Don't forget the ?. Example: https://example.com/shop/?vildemomode. This method even works on websites with caching turned on. It will use the default settings.

view_item_list event test mode

view_item_list event test mode 2

Cross Domain Linker Settings for Google

Googles domain linker functionality enables two or more related sites on separate domains to be measured as one. You'll find more information about this functionality here and here.

The domain linker values need to be passed as an array to the filter. The plugin will then output all values as a JavaScript formatted domain linker script.

You'll find a list of all possible parameters over here.

Basic example with multiple domains: You can list multiple string values in the domain's property. When the domain's property has at least one value, gtag.js will accept incoming domain links by default. This allows you to use the same code snippet on every domain.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_google_cross_domain_linker_settings', function (){

return [
"domains" => [
'example.com',
'example-b.com',
]
];
});

Example output:

gtag('set', 'linker', {
'domains': ['example.com', 'example-b.com']
});

decorate_forms: If you have forms on your site that point to the destination domain, set the decorate_forms property to true.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_google_cross_domain_linker_settings', function (){

return [
"domains" => [
'example.com',
'example-b.com',
],
"decorate_forms" => true,
];
});

url_position: To configure the linker parameter to appear in the URL after a fragment (#) instead of as a query parameter (?) (e.g. https://example.com#_gl=1~abcde5~), set the url_position parameter to fragment.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_google_cross_domain_linker_settings', function (){

return [
"domains" => [
'example.com',
'example-b.com',
],
"decorate_forms" => true,
"url_position" => 'fragment',
];
});

accept_incoming: Once a user arrives at a page on the destination domain with a linker parameter in the URL, gtag.js needs to be configured to parse that parameter.

If the destination domain has been configured to automatically link domains, it will accept linker parameters by default. No additional code is required on the destination domain.

If the destination domain is not configured to automatically link domains, you can instruct the destination page to look for linker parameters. Set the accept_incoming property to true.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_google_cross_domain_linker_settings', function (){

return [
"accept_incoming" => true
];
});

Custom Brand Taxonomy

If you are using your own product attribute to store brand names for products, you can use this filter to output the brand names for the pixels. The filter must return the taxonomy name for the brand attribute. Usually, it is the attribute slug, prefixed with pa_. In this example, it would be pa_custom-brand. Depending on how the taxonomy has been created, it also can only be the slug custom-brand. If one doesn't work make sure to try the other.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_custom_brand_taxonomy', function (){

return 'pa_custom-brand';
});

Disable adding the tax to product prices

By default, the Pixel Manager outputs the prices on product pages depending on the tax settings in WooCommerce. Some themes don't use the same logic and display product prices without tax, even though the setting in WooCommerce is set to display them including the taxes. In those cases, the Pixel Manager will still output the prices with tax. If you want to instruct the Pixel Manager to also output the products without taxes, please use the following filter.

info

Don't mix this up with the setting for the purchase confirmation page. The plugin offers a setting to include or exclude tax and shipping on the purchase confirmation page. This is a different setting and only affects the output for the conversion pixels on the purchase confirmation page.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_output_product_prices_with_tax', '__return_false');

Add Facebook tracking exclusion patterns

Facebook doesn't allow the tracking of URLs that contain potentially violating personal data (PII). This is why Facebook has implemented a check that under certain conditions detects such URLs and throws a warning in the event manager.

Such a URL might look like this: https://example.com/shop-feature/?firstname=John&lastname=Doe

By default, the Pixel Manager tracks all URLs, because generally WordPress and WooCommerce don't add PII data to URLs. But, WordPress and WooCommerce customizations may add such PII to URLs. In such a case you might run into warning messages in the Facebook event manager, requesting you to fix those.

In order to address this, we implemented a filter that gives you the option to add URL exclusion patterns. Once activated the Pixel Manager will exclude all URLs from tracking in Facebook that match one or more of the exclusion patterns that have been added to the configuration.

The patterns that you can use are regular expression string patterns. In the background, the Pixel Manager uses a RegExp constructor which you can feed with those string patterns. Take a look at this article to get a better idea of how such a pattern can be constructed. Or, take a look at regex101.com with the following example, which shows a way to construct a matching pattern (take note of the backslashes which are necessary to escape forward slashes in the URL).

/wp-content/themes/child-theme/functions.php
add_filter('pmw_facebook_tracking_exclusion_patterns', function($patterns) {

$patterns[] = 'parcel-panel';

return array_unique($patterns);
});

Block IPs from all tracking (browser and server-side)

From version 1.57.1 the Pixel Manager supports a unified IP exclusion filter pmw_ip_exclusion_list that blocks all tracking for specified IPs:

  • Browser pixel firing (e.g. fbq(), gtag(), ttq(), pintrk()) — suppressed on the frontend
  • Browser-initiated server-to-server events (add_to_cart, page_view, etc.) — blocked before sending
  • Server-side purchase events (CAPI / S2S purchase hits) — blocked on the WooCommerce server
  • SSP purchase proxy events — blocked before sending to SweetCode Cloud

The IPs can be written either as normal IPs or as CIDR ranges. IPv4 and IPv6 are supported.

Learn more about how to specify a CIDR range over here: https://www.ipaddressguide.com/cidr

Frontend IP detection

When the exclusion list is populated, the Pixel Manager automatically activates client-side IP detection (via external services like Cloudflare, ipify, etc.) to determine the visitor's IP, even if no server-to-server integration is active. This adds a small initial delay (~100ms) on the first page load while the IP is fetched and cached for the session.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_ip_exclusion_list', function($ip_exclusions) {

// Exact IPv4 address
$ip_exclusions[] = '203.0.113.50';

// IPv4 CIDR range (entire /24 subnet)
$ip_exclusions[] = '198.51.100.0/24';

// Exact IPv6 address
$ip_exclusions[] = '2001:db8::1';

// IPv6 CIDR range
$ip_exclusions[] = '2001:db8::/32';

return array_unique($ip_exclusions);
});
Deprecated filter

The older pmw_exclude_ips_from_server_2_server_events filter is deprecated since version 1.57.1 but still works for backward compatibility. It only blocked browser-initiated S2S events. Migrate to pmw_ip_exclusion_list to also block browser pixels and server-side purchase events.

Block IPs from server-to-server events (deprecated)

Deprecated since 1.57.1

This filter is deprecated. Use pmw_ip_exclusion_list instead, which provides broader coverage including browser pixels and server-side purchase events.

From version 1.27.8 the Pixel Manager automatically prevents server-to-server events that are triggered by known bots. This reduces the load on the server.

The following filter allows users of the Pixel Manager to add more IPs and IP ranges to the exclusion list.

The IPs can be written either as normal IPs or as CIDR ranges.

Learn more about how to specify a CIDR range over here: https://www.ipaddressguide.com/cidr

/wp-content/themes/child-theme/functions.php
add_filter('pmw_exclude_ips_from_server_2_server_events', function($ip_exclusions) {

// normal IP
$ip_exclusions[] = '123.123.123.123';

// CIDR range
$ip_exclusions[] = '123.123.123.123/32';

return array_unique($ip_exclusions);
});

Disable subscription renewal tracking for all tracking pixels

Stops the Pixel Manager from reporting WooCommerce Subscriptions renewal orders, on every pixel.

info

Covers every pixel as of Pixel Manager Pro 1.67.1. Earlier versions read this filter in the Meta Conversions API and the GA4 Measurement Protocol only, so renewals kept reaching Google Ads, TikTok, Pinterest, Snapchat, Reddit, OpenAI, Nextdoor, Microsoft Advertising and Mixpanel as ordinary purchases.

A renewal is a paid WooCommerce order like any other, so by default it is reported like any other sale: every active server-side integration receives a purchase event for it. That is what most shops want, because the renewal is real revenue. Shops that would rather tie their reporting to acquisition alone, and count a customer once rather than every month, can switch it off.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_subscription_renewal_tracking', '__return_false');

Add it in your theme's functions.php or a snippets plugin rather than on a late hook. The Meta Conversions API reads it while it registers its subscription hooks, which happens early in the request.

What the filter switches off:

  • the server-side purchase event to every platform
  • Meta's RecurringSubscriptionPayment lifecycle event
  • the browser-side conversion on a manual renewal. Those are paid through the checkout, so unlike an automatic renewal they do reach the order confirmation page and would otherwise fire the browser pixels
  • the Automatic Conversion Recovery, which would otherwise recover the very conversions you just switched off

What it leaves alone:

  • the initial subscription order, which keeps firing as a normal purchase on every pixel
  • Meta's Subscribe and CancelSubscription lifecycle events
  • the Google Ads conversion adjustments feed, which still retracts a cancelled or refunded renewal. An adjustment Google Ads cannot match is ignored, while holding it back would leave a conversion standing that had been reported before you added the filter

Disable Google Analytics subscription renewal tracking

Keeps renewals out of Google Analytics 4 while the ad platforms keep receiving them.

info

Effective as of Pixel Manager Pro 1.67.1. The filter existed earlier, but it only gated one of the paths that report a renewal, so renewals reached Google Analytics through the regular purchase path all the same.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_google_analytics_subscription_renewal_tracking', '__return_false');

Refunds follow the purchases: a renewal that is not reported gets no refund event either, so Google Analytics is never asked to reverse revenue it never received. A renewal that was reported before you added the filter keeps its refund, so no revenue is left standing.

Disable Facebook CAPI subscription renewal tracking

Keeps renewals out of Meta while the other platforms keep receiving them.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_facebook_subscription_renewal_tracking', '__return_false');

This covers both ways a renewal reaches Meta: the Purchase event for the renewal order and the RecurringSubscriptionPayment lifecycle event. Subscribe on the initial order and CancelSubscription are unaffected.

info

On Pixel Manager Pro 1.65.0 to 1.67.0 this filter had no effect while the Purchase Proxy was active, because the renewal check could not recognise a renewal on that path. Every renewal was sent to Meta as a Purchase regardless of the filter. Fixed in 1.67.1.

Disable Google Analytics refund tracking

info

Available in Pixel Manager Pro 1.66.0 and later.

With the GA4 Measurement Protocol configured, the Pixel Manager reports every refund to Google Analytics as a refund event, so the property's revenue is corrected. Those events are sent from the WooCommerce admin, days after the customer's visit, so they carry no session and Google Analytics files the reversed revenue under "(not set)".

Use the pmw_google_analytics_refund_tracking filter to switch the refund events off entirely.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_google_analytics_refund_tracking', '__return_false');
caution

With the refund events switched off, the revenue Google Analytics reports stays overstated by the refunded amounts. Only use this if a clean attribution report is worth more to you than a correct revenue figure.

To keep refunds for most orders and skip them only for some, filter the payload instead. Refund payloads run through the server-side event filter pipeline under the event name refund, so returning null blocks a single refund event:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_server_event_payload_google_analytics_refund', function ($payload, $pixel_name, $event_name) {

// Keep small refunds out of Google Analytics.
if (isset($payload['events'][0]['params']['value']) && $payload['events'][0]['params']['value'] < 10) {
return null;
}

return $payload;
}, 10, 3);

Read more about how refunds are reported on the Google Analytics configuration page.

Suppress the browser purchase conversion for specific orders

info

Available in Pixel Manager 1.31.2 and later, in both the free and the pro version.

Use the pmw_conversion_prevention filter to stop the Pixel Manager from firing the browser purchase conversion for an individual order. Returning true withholds the order data from the data layer on the order received page, which means no browser pixel fires a purchase event for that order: not Google Ads, not Meta, not Google Analytics, none of them.

The filter receives two arguments:

ArgumentTypeDescription
$preventboolWhether to suppress the conversion. Default false.
$orderWC_OrderThe order the confirmation page was reached for.

What it does and does not cover

  • It affects the browser purchase conversion only. Server-side purchase events run on order status transitions and are gated separately. To suppress those, use pmw_skip_s2s_purchase_event.
  • It is an addition to the checks the Pixel Manager already performs. Orders in failed, cancelled or refunded status, and visits by user roles excluded from tracking, never fire a purchase conversion in the first place.
  • Because no pixel fires, the Pixel Manager does not write its duplication prevention marker on the order. The order therefore stays eligible for Automatic Conversion Recovery (pro), which is what makes the deferral pattern below work.

Deferring a conversion until the order is paid

The most common use for this filter is a payment gateway that creates orders in pending payment status and confirms the payment later: bank transfer, invoice, manual review, or a custom gateway. The customer still lands on the order received page, so the browser purchase conversion fires for an order that may never be paid.

Write the filter so it evaluates the current order status rather than suppressing the gateway outright. ACR re-evaluates this same filter on the customer's next visit to the shop, so as soon as the order reaches a paid status the filter returns false and the full purchase conversion is recovered, including the Google Ads conversion.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_conversion_prevention', function ($prevent, $order) {

if (!$order instanceof WC_Order) {
return $prevent;
}

// Only this gateway is affected. Every other gateway keeps its current behavior.
if ($order->get_payment_method() !== 'my_custom_gateway') {
return $prevent;
}

// Hold the conversion back until the order reaches a paid status.
// wc_get_is_paid_statuses() returns `processing` and `completed` by default.
if (!in_array($order->get_status(), wc_get_is_paid_statuses(), true)) {
return true;
}

return $prevent;
}, 10, 2);
caution

Make the suppression conditional on the order status, as in the example above. A filter that returns true for a gateway unconditionally discards the conversion permanently, because the order never becomes eligible for recovery either.

Orders recovered this way are reported in the ACR column of the Payment Gateway Tracking Accuracy report, so you can verify that the deferral works instead of silently losing conversions.

Requirements and limits of the deferred conversion

The recovery half of this pattern depends on ACR, so its requirements apply: the customer has to return to the shop with the same browser after the order reaches a paid status. If that never happens, the conversion is not recorded at all.

For platforms that have a server-side counterpart in the Pixel Manager, prefer the Status-Driven Purchase Conversions recipe instead. It routes the purchase through the platform's Conversion API, which fires on the paid-status transition itself and needs no return visit. Google Ads has no server-side purchase API in the Pixel Manager, which is why the filter above combined with ACR is the available route for Google Ads conversions.

Skip server-side purchase events for specific orders

info

Available in Pixel Manager Pro 1.58.10 and later.

Use the pmw_skip_s2s_purchase_event filter to prevent the Pixel Manager from firing server-side purchase events for specific orders. Returning true skips the purchase event for every server-side platform (Facebook CAPI, TikTok Events API, Pinterest Conversions API, Snapchat CAPI, Reddit CAPI, and GA4 Measurement Protocol), including the SweetCode Cloud (SSP) proxy path. The order is also excluded from the Google Ads Conversion Adjustments CSV feed so it cannot later be sent as a RETRACT or RESTATE adjustment.

The filter receives three arguments:

ArgumentTypeDescription
$skipboolWhether to skip the purchase event. Default false.
$orderWC_OrderThe WooCommerce order.
$contextstringThe pixel class name (e.g. SweetCode\Pixel_Manager\Pixels\Facebook\Facebook_CAPI) or conversion_adjustments_feed.

Common use case: exclude marketplace orders that were imported programmatically (Amazon, eBay, etc.) and therefore should not be counted as conversions.

The following example skips every server-side purchase event for orders imported by the magnalister plugin. Magnalister prefixes every imported order's customer note with magnalister-Verarbeitung, which makes the match simple regardless of the source marketplace.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_skip_s2s_purchase_event', function ($skip, $order, $context) {

// Skip every PMW server-side purchase event and Google Ads conversion
// adjustment for magnalister-imported marketplace orders.
if (strpos((string) $order->get_customer_note(), 'magnalister-Verarbeitung') === 0) {
return true;
}

return $skip;
}, 10, 3);

You can also target a specific platform by checking the $context argument:

/wp-content/themes/child-theme/functions.php
use SweetCode\Pixel_Manager\Pixels\Facebook\Facebook_CAPI;

add_filter('pmw_skip_s2s_purchase_event', function ($skip, $order, $context) {

// Only skip the Facebook CAPI purchase event, leave all other platforms alone.
if ($context === Facebook_CAPI::class && $order->get_payment_method() === 'some_gateway') {
return true;
}

return $skip;
}, 10, 3);

Filter the Google Ads Conversion Adjustments feed

info

Available in Pixel Manager Pro 1.60.1 and later.

Use the pmw_conversion_adjustments_feed_row filter to exclude or modify individual rows of the Google Ads Conversion Adjustments CSV feed (the RETRACT / RESTATE feed built from cancelled orders and refunds).

Return an empty value (null, false, or []) to drop a row from the feed. You can also modify the row's fields; the Pixel Manager re-applies its own validation afterwards (clamping negative values to 0, enforcing Google's column order), so the feed always stays within Google's spec.

This is the recommended way to customize the feed. Unlike pmw_skip_s2s_purchase_event, it only affects the feed, so there is no risk of accidentally suppressing your live server-side purchase events.

The filter receives three arguments:

ArgumentTypeDescription
$rowarrayThe associative row data (see keys below).
$orderWC_OrderThe order being adjusted.
$typestringThe adjustment source: cancelled or refund.

The $row array has the following keys:

KeyDescription
order_idThe order number Google uses to match the original conversion.
conversion_nameThe configured conversion name.
adjustment_timeISO 8601 timestamp, e.g. 2026-06-25T13:00:00+00:00.
adjustment_typeRETRACT or RESTATE.
adjusted_valueThe new order value (RESTATE only; empty for RETRACT).
currencyThe currency code (RESTATE only).

Example: only send adjustments for orders that came from a Google Ads click

The following example drops every order that has no Google Ads click ID. The Pixel Manager stores the click ID on the order as _wpm_gclid when the customer reaches the order received page. Orders imported from marketplaces (Amazon, eBay, etc. via Channable, M2E Cloud, magnalister, and similar integrators) never reach that page, so they never carry a click ID and are dropped.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_conversion_adjustments_feed_row', function ($row, $order) {

// Drop orders that have no Google Ads click ID recorded.
if (empty($order->get_meta('_wpm_gclid', true))) {
return null;
}

return $row;
}, 10, 2);
warning

Filtering the feed reduces noise in your Google Ads logs, but it does not improve the accuracy of your data, and it can reduce it.

Google also matches conversions through Enhanced Conversions (hashed email and phone number) even when no readable click ID is present. Those orders have no local _wpm_gclid, so a click-ID filter will drop their legitimate RETRACT / RESTATE adjustments, and Google will keep counting the original (now cancelled or refunded) conversion.

Google's own documentation states that the "this conversion does not exist" responses can be safely ignored. We recommend uploading all adjustments and ignoring those warnings, and we treat the contradiction between that documentation and the warnings shown in the Google Ads UI as a low-priority inconsistency on Google's side. Use this filter only if you want to quiet the logs, not as a fix for conversion accuracy.

Mark custom order flows as backend-manual

info

Available in Pixel Manager Pro 1.58.10 and later.

Use the pmw_is_backend_manual_order filter to teach the Pixel Manager about custom order-creation flows (B2B quote-to-order, push-cart, pay-for-order, etc.) that neither set _created_via = 'admin' nor trigger WooCommerce Order Attribution. When an order is recognized as backend-manual, the Pixel Manager re-captures the customer's browser identifiers on the purchase confirmation page so server-side purchase events carry the real customer context instead of being empty or attributed to the staff member who created the order.

The filter receives two arguments:

ArgumentTypeDescription
$is_backend_manualboolWhether PMW already considers this a backend-manual order.
$orderWC_OrderThe WooCommerce order being evaluated.

Example: flag every order created by a custom quote plugin that stores its origin in order meta.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_is_backend_manual_order', function ($is_backend_manual, $order) {

if ($order->get_meta('_my_quote_plugin_origin') === 'staff_quote') {
return true;
}

return $is_backend_manual;
}, 10, 2);

Enable Facebook Hybrid Mobile App Events

If you're using a wrapper to make your website available as a hybrid mobile app on iOS or Android, you can use the following filter to enable the Facebook hybrid mobile app events bridge.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_facebook_mobile_bridge_app_id', function () {
return 'YOUR_APP_ID';
});
note

Find more information about the Facebook hybrid mobile app events bridge over here

Add more selectors for specific events

If you are using a custom theme that doesn't implement the standard WooCommerce classes on buttons like add-to-cart or begin-checkout, the events won't be triggered. In this case, you can use the following filters to add more selectors for specific events.

note

First try to use the body selector. In most cases, this alone will work and fix the trigger.

note

Don't use document as selector. It won't work.

add-to-cart event

First, try the body selector. In most themes, this will work.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_add_selectors_add_to_cart', function () {
return [
'body',
];
});

If that doesn't work, you'll have to add a selector that is specific to the button that triggers the add-to-cart event.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_add_selectors_add_to_cart', function () {
return [
'.custom-add-to-cart-selector',
];
});

begin-checkout event

First, try the body selector. In most themes, this will work.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_add_selectors_begin_checkout', function () {
return [
'body',
];
});

If that doesn't work, you'll have to add a selector that is specific to the button that triggers the begin-checkout event.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_add_selectors_begin_checkout', function () {
return [
'.custom-begin-checkout-selector',
];
});

Order Items Filter

Filters the line items of an order before the Pixel Manager builds the reported item list from them.

This is the single place where the reported line items of a sale are decided. The filter runs for the browser purchase event and for every server-side purchase event (all Conversion APIs and the Google Analytics Measurement Protocol), so one callback covers all of them.

info

The pmw_ name is available since version 1.32.0. It replaced wpm_order_items, which still works but is deprecated.

The filter receives the items as WooCommerce returns them from $order->get_items(), keyed by order item ID, plus the order.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_order_items', function ($order_items, $order) {

// Do not report the shipping insurance product.
foreach ($order_items as $item_id => $item) {
if (1234 === $item->get_product_id()) {
unset($order_items[$item_id]);
}
}

return $order_items;
}, 10, 2);
note

Two things happen after this filter, so plan around them:

  • The children of bundles and composite products are collapsed into their container. The array you receive still contains them.
  • pmwDataLayer.order.quantity is the count of the items that survive the filter, so removing an item also lowers that number.
warning

Removing an item changes the reported item list, not the order value. Use the marketing conversion value filter or the analytics order value filters when the value has to match the items.

Order Fees Filter

This filter controls the payment processor fees that the Pixel Manager deducts from the marketing conversion value. These are the fees your payment provider keeps out of your payout: the customer never pays them, and they are not part of any WooCommerce order figure. They are deducted under both the Order Subtotal and the Profit Margin option in General → Order configuration → Marketing value logic.

Unlike taxes and shipping costs, which are standardized in WooCommerce, payment gateway fees have no standard storage location. Some gateways save them in a dedicated order meta field, and many do not save them at all. The Pixel Manager reads them for the popular gateways listed under Shop Settings. For every other gateway, use this filter to calculate them yourself.

The filter runs each time a conversion value is calculated: for the browser event when the order confirmation page loads, and for the server-side events at the end of the request in which the gateway marked the order as paid. A fee the gateway stores later than that, for instance through a webhook, is not on the order yet at either moment, so $order_fees does not include it. Calculating the fee from the payment method and the order total inside this filter, as in the example below, does not depend on the gateway having stored anything. See when the fee is deducted.

It changes what your conversion action reports

Adding a fee here lowers the value sent to the ad platforms from the day the filter goes live, under Order Subtotal as well as under Profit Margin. That is a step change in your reported revenue series with nothing in the settings to explain it, so plan for the discontinuity.

It also means you must not deduct the same fee a second time anywhere else. Under Profit Margin the margin already has $order_fees taken off it, so a fee subtracted both here and in your own profit calculation is counted twice.

warning

Since version 1.65.0, $order_fees no longer includes amounts that were added to the order as a WooCommerce order fee (a gift wrap fee, a cash on delivery surcharge, or a deposit instalment).

Such a surcharge is money the customer pays, not a cost, and the WooCommerce order subtotal never contained it, so deducting it removed it a second time and reported less than the products were worth. If you relied on the previous behaviour, add $order->get_total_fees() back inside this filter.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_order_fees', function($order_fees, $order){

// The $order_fees variable contains the payment processor fees
// that the Pixel Manager has been able to extract from the
// order meta fields of popular payment gateways.
// You can use the value of $order_fees as a starting point
// and add your own calculated fees to it. Or you can
// completely override the value of $order_fees
// and return your own value.

// If the payment method is braintree_cc
// then the order fee is 0.29 + 2.09% of the order total.
// Add it to the order_fees.
if ($order->get_payment_method() == 'braintree_cc') {
$order_fees += 0.29 + ($order->get_total() * 0.0209);
}

return $order_fees;
}, 10, 2);

Order Shipping Profit Filter

info

This filter is available in version 1.67.1 and later.

The Profit Margin calculation leaves shipping out on both sides: the shipping the customer paid is not counted as revenue, and no carrier cost is deducted. WooCommerce records what you charged for shipping, but nothing anywhere records what the carrier charged you, so the Pixel Manager cannot derive it and deducts nothing.

Use pmw_order_shipping_profit to supply what shipping actually earned or cost you on an order. Whatever you return is added to the margin as-is.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_order_shipping_profit', function ($shipping_profit, $order) {

// What the customer paid for shipping, minus what the carrier charges you.
// Both figures net of tax.
$courier_cost = 28.81;

return (float) $order->get_shipping_total()
- (float) $order->get_total_shipping_refunded()
- $courier_cost;
}, 10, 2);

Three things to get right:

  • Work in net figures. Every other figure in the calculation is net of tax, and get_shipping_total() is net as well. A carrier rate entered tax-inclusive is wrong by its tax on every single order, and the error is small and constant enough to go unnoticed.
  • Subtract refunded shipping. Nothing else in the margin deducts it, so a partially refunded order otherwise overstates the profit.
  • Free shipping still costs you. Deciding the carrier cost from what the customer was charged means an order over your free-shipping threshold gets no cost deducted at all, which is exactly the order where it hurts most. Decide it from the shipping method, not from the amount. The Profit and POAS tracking recipe shows how.

This filter runs inside the profit margin calculation only. It therefore affects the conversion value only while Marketing value logic is set to Profit margin, and it never touches the Order subtotal or Order total logic. It also feeds anything else built on the margin, including your own calls to Profit_Margin::get_order_profit_margin().

Profit Margin API

Two methods on \SweetCode\Pixel_Manager\Profit_Margin are supported for use from shop code. Both take a WC_Order.

MethodReturns
Profit_Margin::get_order_profit_margin($order)The profit margin of the order, as described under Profit Margin. Available since 1.35.1.
Profit_Margin::order_has_complete_cogs($order)true when a cost of goods is known for every product line of the order. Available since 1.67.1.

order_has_complete_cogs() exists because a product without a cost is counted with a cost of zero, which reports that product's whole revenue as profit, and the margin is a plain number that cannot tell you so. Ask this before you act on a profit figure, rather than reimplementing the plugin's cost lookup in your own code.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_custom_order_parameters', function ($custom_parameters, $order) {

if (!class_exists('\SweetCode\Pixel_Manager\Profit_Margin')) {
return $custom_parameters;
}

// Send no profit at all rather than a figure that is too high because
// one product has no cost on it.
if (!\SweetCode\Pixel_Manager\Profit_Margin::order_has_complete_cogs($order)) {
return $custom_parameters;
}

$custom_parameters['profit'] = round(
(float) \SweetCode\Pixel_Manager\Profit_Margin::get_order_profit_margin($order),
2
);

return $custom_parameters;
}, 10, 2);
note

The class name, its namespace and these two signatures stay where they are. Everything else on the class is internal and may change without notice. Keep the class_exists() check: the class is not loaded when WooCommerce is inactive.

A line item whose product was deleted

Both methods skip a line item whose product no longer exists, the same way the calculation does. An order whose products were all deleted therefore reports true and a margin of zero, which is correct in the sense that there is nothing left to price, but is not a profit figure worth reporting.

Split Payment Order Role

Deposit and partial-payment plugins split one sale across several WooCommerce orders. The Pixel Manager reports each sale once, in full, at the moment the deposit is paid, on the order that represents the sale. Since version 1.65.0 this works out of the box for Deposits & Partial Payments for WooCommerce (Acowebs, free and Pro) and WooCommerce Deposits (Webtomizer, woocommerce.com).

If you use a different deposits plugin, the pmw_split_payment_order_role filter tells the Pixel Manager what role an order plays:

  • standard — a regular order, tracked normally.
  • payment_leg — the order only collects an instalment for a sale that lives on its parent order. The purchase is reported with the parent order's products and value, and the duplication prevention marker is written on the parent, so the other instalments of the same sale stay silent. Server-side purchase events for the order itself are skipped.
  • follow_up_invoice — the order re-invoices a part of a sale that was already reported when its parent order was placed. It never reports a purchase, neither in the browser nor server-side.
/wp-content/themes/child-theme/functions.php
add_filter('pmw_split_payment_order_role', function ($role, $order) {

// Example: a deposits plugin that stores its instalment orders
// with a custom created_via and the sale on the parent order.
if (
$order instanceof WC_Order
&& 'my_deposits_plugin' === $order->get_created_via()
&& $order->get_parent_id() > 0
) {
return 'payment_leg';
}

return $role;
}, 10, 2);

For payment_leg orders the parent must be a regular shop order that carries the product line items, otherwise the Pixel Manager falls back to standard handling.

Set the maximum of orders to analyze for the tracking accuracy analysis

The tracking accuracy analysis may take too much time to complete. This is especially the case if you have a slow server, a short PHP timeout, or a clogged Action Scheduler queue.

The following filter allows you to set the maximum number of orders that should be analyzed.

Try 100 orders first. If that works, you can increase the number.

The analysis runs overnight, so you'll have to wait until the next day to see the results.

If that doesn't help, you'll probably need to fix the Action Scheduler queue.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_tracking_accuracy_analysis_max_order_amount', function () {
return 100;
});

Adjust Outbrain event name mapping

If you've been working with Outbrain before and have been using different event names than the default ones in the Pixel Manager, you can use the following filter to adjust the event name mapping.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_outbrain_event_name_mapping', function ( $mapping ) {
$mapping['purchase'] = 'purchase';

return $mapping;
});

Adjust Taboola event name mapping

If you've been working with Taboola before and have been using different event names than the default ones in the Pixel Manager, you can use the following filter to adjust the event name mapping.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_taboola_event_name_mapping', function ( $mapping ) {
$mapping['purchase'] = 'purchase';

return $mapping;
});

Suppress the version info output in the developer console

The Pixel Manager prints a single line to the browser console on every page load, even when the Console Logger is switched off:

Pixel Manager for WooCommerce: pro | distro: fms | active license: yes | version: 1.63.0

If you want to suppress it, you can use the following filter.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_show_version_info', '__return_false');
info

This filter is available in version 1.58.5 and later.

The line isn't removed, it's demoted into the Console Logger. With the logger off nothing is printed, and it reappears when you enable the logger with ?pmwloggeron for debugging.

Add custom parameters to the Google Analytics purchase event

info

These filters are only available in version 1.44.0 and later.

The Pixel Manager automatically sends various standard parameters to Google Analytics. With the custom order parameters filters, you can add additional parameters to the Google Analytics purchase event on order and order item level.

Order level custom parameters

Use cases for order level custom parameters are:

  • Customer segmentation
    • Based on total order value
    • Based on the number of orders
  • Weather conditions at the location of the customer at the time of the purchase
  • Expected delivery time

Order level custom parameters example

/wp-content/themes/child-theme/functions.php
add_filter('pmw_custom_order_parameters', function ( $custom_parameters, $order ) {

$custom_parameters['custom_parameter_a'] = 'custom_value_a';
$custom_parameters['custom_parameter_b'] = 'custom_value_b';

return $custom_parameters;
}, 10, 2);

Order item level custom parameters

Use cases for order item level custom parameters are:

  • Supplier for this particular product on this particular order
  • Customization of the product
  • Gift wrapping option

Order item level custom parameters example

/wp-content/themes/child-theme/functions.php
add_filter('pmw_custom_order_item_parameters', function ( $custom_parameters, $order_item, $order ) {

$custom_parameters['custom_parameter_1'] = 'custom_value_1';
$custom_parameters['custom_parameter_2'] = 'custom_value_2';

return $custom_parameters;
}, 10, 3);

How to use the Google Analytics custom parameters filters

  1. Add the custom parameters to the Google Analytics purchase event by using one or both of the filters above.

  2. Configure the custom parameters in Google Analytics as custom dimensions or metrics:

  3. Wait one day for the data to be processed by Google Analytics.

  4. Now you can use the custom parameters in Google Analytics reports.

Filter script opening attributes

info

These filters are only available in version 1.45.1 and later.

Example: Add the Cloudflare data-cfasync attribute to the script tag.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_opening_script_string_attributes', function ( $attributes ) {

// The value is an array of text strings that will be concatenated.
$attributes['data-cfasync'] = ['false'];

return $attributes;
});

Filter the Pixel Manager options

info

This filter is only available in version 1.46.2 and later.

Every now and then you might have a special setup or a special requirement that can't be fulfilled by using the standard settings. In such cases, you can use the following filter to adjust the Pixel Manager's options before it processes them.

warning

Be aware that we might change the structure of the settings array in future versions. So be careful when using this filter. Changes to structure happen very rarely, but they can happen.

/wp-content/themes/child-theme/functions.php
/**
* Purpose: Filter the Pixel Manager's options before it processes them.
*
* Place this code into functions.php of your child theme.
*
* Example:
* Some shops use the same install to serve on different domains.
* The following example shows how to adjust the Google Analytics measurement ID based on the host.
* You can use the same logic to adjust any other pixel ID or setting.
**/

add_filter('pmw_options', function ($options) {

// Use the error_log to get a better understanding of the options array.
// error_log('options: ' . print_r($options, true));

$host = $_SERVER['HTTP_HOST'];

if (preg_match("/.*example.nl/", $host)) {
$options['google']['analytics']['ga4']['measurement_id'] = 'abc';
} elseif (preg_match("/.*example.us/", $host)) {
$options['google']['analytics']['ga4']['measurement_id'] = 'def';

}

return $options;
});

Google tag ID

With the following filter you can override the default Google tag ID. The override is applied on every request, so it takes effect even when the tag ID is cached.

info

The pmw_google_tag_id filter is available as of version 1.60.1. In earlier versions (1.58.5 to 1.60.0) use google_tag_id instead; it still works as a deprecated alias.

/wp-content/themes/child-theme/functions.php
<?php

/**
* Override the default Google tag ID
*/
add_filter('pmw_google_tag_id', function ($tag_id) {
return "AW-1234567890";
});

Suppress Cart Item Inline Script Output

info

This filter is only available in version 1.54.2 and later.

Some themes use JavaScript-based renderers that don't properly hide <script> tags, causing them to be visible on the page. This is a theme issue, but if you can't easily change the theme, you can use this filter to suppress the inline script output for cart item data.

The Pixel Manager outputs small inline <script> tags after each cart item name to track cart interactions (like remove_from_cart events). When these scripts are suppressed, the plugin falls back to loading the cart item data via AJAX, so tracking continues to work.

Filter Signature

apply_filters('pmw_output_cart_item_data', $output, $cart_item, $cart_item_key, $action)
ParameterTypeDescription
$outputboolWhether to output the script. Default: true
$cart_itemarrayCart item data containing product_id and variation_id
$cart_item_keystringUnique cart item key
$actionstringThe current action hook name (see below)

Action Hook Values

The $action parameter tells you which hook triggered the output:

  • woocommerce_after_cart_item_name - Cart page
  • woocommerce_after_mini_cart_item_name - Mini cart widget
  • woocommerce_mini_cart_contents - Mini cart fallback

Examples

Suppress all cart item inline scripts:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_output_cart_item_data', '__return_false');

Suppress only on the cart page:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_output_cart_item_data', function($output, $cart_item, $cart_item_key, $action) {
if ($action === 'woocommerce_after_cart_item_name' && is_cart()) {
return false;
}
return $output;
}, 10, 4);

Suppress on cart and checkout pages:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_output_cart_item_data', function($output, $cart_item, $cart_item_key, $action) {
if ($action === 'woocommerce_after_cart_item_name' && (is_cart() || is_checkout())) {
return false;
}
return $output;
}, 10, 4);

Suppress only in mini cart:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_output_cart_item_data', function($output, $cart_item, $cart_item_key, $action) {
if (in_array($action, ['woocommerce_after_mini_cart_item_name', 'woocommerce_mini_cart_contents'])) {
return false;
}
return $output;
}, 10, 4);

Product Data Layer Output in Product Loops

info

These filters are only available in version 1.62.1 and later.

The Pixel Manager outputs a hidden marker element and a small inline <script> tag after each product in WooCommerce product loops (through the woocommerce_after_shop_loop_item hook). This output powers the view_item_list and select_item events for product lists.

Some page builders and themes sanitize the output of that hook. The tags get stripped, and the content of the script becomes visible as raw text inside each product card. Known examples are the Elementor Products widget and theme builders that render their own product cards. This is a page builder issue, but if you can't wait for a fix, the Pixel Manager provides two filters to work around it.

Defer the output to the footer (recommended)

The pmw_defer_product_data_layer_to_footer filter moves the product data layer output into wp_footer, out of reach of sanitizing page builders, and keeps tracking fully working. The Pixel Manager prints the data scripts in the footer and re-inserts the marker elements into the product cards with a small script (matched through the standard WooCommerce post-{id} loop item class).

Filter Signature

apply_filters('pmw_defer_product_data_layer_to_footer', $defer, $product)
ParameterTypeDescription
$deferboolWhether to defer the output to the footer. Default: false
$productWC_ProductThe product being output

Defer everywhere (start here):

/wp-content/themes/child-theme/functions.php
add_filter('pmw_defer_product_data_layer_to_footer', '__return_true');

This works no matter which page builder, theme or widget renders your product grids. Use it first to confirm that the filter solves your problem. If it does, you can narrow it down to the specific widget afterwards.

Defer only inside the Elementor Products widget:

caution

The woocommerce-products widget is part of Elementor Pro. If you only run the free Elementor plugin, or your product grid comes from your theme (for example a theme builder module), this snippet never runs and nothing changes. Use the global filter above instead.

/wp-content/themes/child-theme/functions.php
add_action('elementor/frontend/widget/before_render', function ($widget) {
if ('woocommerce-products' === $widget->get_name()) {
add_filter('pmw_defer_product_data_layer_to_footer', '__return_true');
}
});

add_action('elementor/frontend/widget/after_render', function ($widget) {
if ('woocommerce-products' === $widget->get_name()) {
remove_filter('pmw_defer_product_data_layer_to_footer', '__return_true');
}
});

The same pattern works for other page builders. Toggle the filter on right before the problematic widget or module renders, and off right after, using the hooks that the page builder provides. Make sure the widget name you check for is the one your grid actually uses, otherwise the filter is never applied.

caution

Products that a widget loads after the initial page render, for example through AJAX pagination or a load-more button, are not covered by the footer pass. Only defer where necessary.

Suppress the output entirely

If you don't need view_item_list and select_item tracking for the affected products, you can suppress the output entirely with the pmw_output_product_data_layer_script filter. All other tracking, such as product pages, cart and purchase events, is unaffected.

Filter Signature

apply_filters('pmw_output_product_data_layer_script', $output, $product, $meta_tag)
ParameterTypeDescription
$outputboolWhether to output the product data layer. Default: true
$productWC_ProductThe product being output
$meta_tagbooltrue for the meta tag output in the head of product pages, false in loop context

Suppress everywhere:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_output_product_data_layer_script', '__return_false');

Suppress only inside the Elementor Products widget:

caution

The woocommerce-products widget is part of Elementor Pro. If you only run the free Elementor plugin, or your product grid comes from your theme, this snippet never runs and nothing changes.

/wp-content/themes/child-theme/functions.php
add_action('elementor/frontend/widget/before_render', function ($widget) {
if ('woocommerce-products' === $widget->get_name()) {
add_filter('pmw_output_product_data_layer_script', '__return_false');
}
});

add_action('elementor/frontend/widget/after_render', function ($widget) {
if ('woocommerce-products' === $widget->get_name()) {
remove_filter('pmw_output_product_data_layer_script', '__return_false');
}
});

SSP Additional Domains (Multi-Domain Support)

info

This filter requires the Server-Side Proxy to be active on your primary domain. Available since Pixel Manager 1.57.1.

If your single WordPress installation serves multiple domains (without WordPress Multisite), you can connect each domain to its own SSP proxy endpoint using this filter. This is useful when a single WooCommerce store is accessible through more than one domain name.

How it works:

  1. Set up the Server-Side Proxy for your primary domain as usual through the Pixel Manager settings.
  2. In the SweetCode Cloud portal, create a new domain entry for each additional domain and copy the sync token.
  3. Add the filter below to your child theme's functions.php.

The Pixel Manager will automatically:

  • Output the correct SSP proxy URL and verification token for visitors on each domain
  • Push your CAPI destination configs to each additional domain's SSP endpoint
  • Keep all domains in sync whenever you update your pixel settings or on the daily sync schedule
/wp-content/themes/child-theme/functions.php
add_filter('pmw_ssp_additional_domains', function ($domains) {

// Add one entry per additional domain
$domains[] = [
'sync_token' => 'ssp_tok_xxxxxxxxxxxx', // Sync token from SweetCode Cloud portal
'proxy_hostname' => 'ssp.otherdomain.com', // The SSP proxy hostname for this domain
'shop_origin' => 'https://otherdomain.com', // The WordPress site URL on this domain
];

// Add more domains as needed
// $domains[] = [
// 'sync_token' => 'ssp_tok_yyyyyyyyyyyy',
// 'proxy_hostname' => 'ssp.thirddomain.com',
// 'shop_origin' => 'https://thirddomain.com',
// ];

return $domains;
});

Parameters for each domain entry:

ParameterDescription
sync_tokenThe domain sync token from the SweetCode Cloud portal. Each domain has its own unique token.
proxy_hostnameThe full SSP proxy hostname (e.g. ssp.otherdomain.com). Must match the domain you created in SweetCode Cloud.
shop_originThe full origin URL of the WordPress site on this domain, including the protocol (e.g. https://otherdomain.com). Must match exactly what appears in the browser's address bar.
caution

The initial config push for additional domains happens on the next daily sync, or you can trigger it from the Pixel Manager under Server-Side → SweetCode Server-Side Proxy. After adding the filter, trigger a sync to activate the additional domains immediately.

tip

The Pixel Manager settings UI only shows the status of your primary SSP domain. To verify that additional domains are synced correctly, check the SweetCode Cloud portal — each domain's sync status, routing status, and event activity are visible there.

Modify the data layer

The pmw_experimental_data_layer filter hands you the complete pmwDataLayer object right before it is printed into the page. Every value the tracking library reads on the front end passes through it: shop, cart, products, user, general and the pixel settings.

info

This filter is available as of version 1.31.2. In earlier versions it was called wpm_experimental_data_layer, which still works as a deprecated alias.

warning

This is a low-level filter. The structure of the data layer can change between releases, so check your customization after an update. Prefer one of the specific filters on this page whenever one exists for what you need.

A common use is to correct the page type on shops whose checkout is rendered by a third-party checkout builder:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_experimental_data_layer', function ($data) {

// Log the data layer to understand its structure
// error_log('pmwDataLayer: ' . print_r($data, true));

if ('cart' === $data['shop']['page_type'] && is_checkout()) {
$data['shop']['page_type'] = 'checkout';
$data['shop']['list_name'] = 'Checkout Page';
$data['shop']['list_id'] = 'checkout';
}

return $data;
});
tip

As of version 1.66.0 the Pixel Manager resolves this particular case on its own, so the snippet above is no longer needed for checkout builders that make is_cart() true on the checkout page.

Disable begin_checkout on checkout page load

The Pixel Manager fires begin_checkout when the checkout page loads with a non-empty cart and no begin_checkout has been sent for that cart yet. This covers shoppers who reach the checkout without clicking a "proceed to checkout" button: funnel builders, buy-now buttons, direct checkout links and block-based carts. Use this filter to switch that trigger off and keep only the click-based trigger.

info

This filter is available as of version 1.62.1. The trigger is on by default.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_fire_begin_checkout_on_checkout_page', '__return_false');

The event is deduplicated against the click-based trigger through a session flag, so leaving the trigger on does not produce a second begin_checkout for the same cart.

Fire a parent view_item on variable product pages

With Variations Output enabled, the Pixel Manager fires no view_item on a variable product page until the shopper selects a variation. WooCommerce preselects no variation out of the box, so on those shops a product page view goes unreported and the visitor joins no remarketing audience for that product. Use this filter to also fire a view_item with the parent product when the page loads.

info

This filter is available as of version 1.66.1. It is off by default.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_fire_parent_view_item_on_variable_products', '__return_true');

The variation's own view_item still fires once the shopper picks a variation, so a shopper who selects one produces two view_item events: the parent on page load, then the variation.

caution

Only switch this on if your product feed contains parent products. For dynamic remarketing, the product ID sent with view_item has to match an item in the uploaded catalog, and with Variations Output enabled the catalog holds the variations, not the parent. A parent ID the catalog does not contain makes the ad platforms report an unmatched item.

If your feed is built around parent products throughout, disable Variations Output instead. That switches all product reporting to parent IDs and needs no filter.

The filter receives the product ID, so the decision can be made per product. That is useful when only part of the catalog is fed as parent products:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_fire_parent_view_item_on_variable_products', function ($fire, $product_id) {

// Only for products in the "bundles" category
return has_term('bundles', 'product_cat', $product_id);
}, 10, 2);

This filter replaces the jQuery pmwLoad snippet that the Tips and Tricks page used to document. The filter cannot break when the tracking library is restructured, which that snippet did.

Turn Meta's automatic configuration off

Meta's pixel loads a configuration from https://connect.facebook.net/signals/config/<pixel_id> on every page view and opts the pixel into the features it names. autoConfig is the opt-in for one of those groups, Meta's AutomaticSetup bundle, whose most visible member is automatic event detection. Use this filter to opt a pixel out of that bundle from your website, without touching the pixel in Events Manager.

info

This filter is available as of version 1.66.1. Meta's automatic configuration is on by default, as Meta ships it.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_facebook_auto_config', function ($enabled, $pixel_id) {
return false;
}, 10, 2);

The Pixel Manager then issues fbq('set', 'autoConfig', false, '<pixel_id>') immediately before it initializes that pixel, which is the only moment fbevents.js honors the setting. The opt-in calls that arrive with the pixel configuration a moment later are issued with Meta's "do not override an opt-out" flag, so they cannot switch the bundle back on.

The filter runs once per configured pixel, so a multi-pixel setup can be handled per pixel:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_facebook_auto_config', function ($enabled, $pixel_id) {

// Only the agency-managed pixel.
if ('123456789012345' === $pixel_id) {
return false;
}

return $enabled;
}, 10, 2);
warning

Turning a single Meta feature off in Events Manager is more targeted, applies to every site and integration that uses the pixel, and is the better fix in almost every case. As of fbevents.js 2.9.393, the bundle this filter opts out of also contains:

  • Microdata scraping and enrichment of legitimate events, and Meta's AutomaticParameters instrumentation. The Pixel Manager's own event data and its advanced matching from order and customer data are unaffected.
  • Meta's regex- and AI-based matching extensions, and SmartSetup including its total-price extraction.
  • Engagement instrumentation: scroll depth, page metadata, and Meta's web chat integration.
  • Future Meta features shipped inside the same bundle.
info

What this filter does not do, because fbevents.js gates each of these on its own opt-in:

  • It does not stop the configuration file from being downloaded and executed. autoConfig is an opt-out, not a switch that keeps the file from loading.
  • It does not stop Event Setup Tool rules or their value extractors. The rule engine installs its own click listener and checks only its own opt-in.
  • It does not stop Meta's Conversions API Gateway (openbridge).
  • It does not stop Meta's base automatic advanced matching, its business-category event restrictions, first-party cookies, or bot blocking.
danger

Never hand-roll this with your own window.fbq placeholder. Meta's bootstrap starts with "if fbq already exists, do nothing", so a foreign fbq defined before the Pixel Manager runs stops fbevents.js from ever loading, and the Meta pixel tracks nothing at all. The Pixel Manager logs a console warning when it detects one.

The debug report lists every pixel this filter disables autoConfig for, under Meta Event Setup Tool.

Block URLs from all browser tracking

Google's ad quality crawlers and Google Translate render a shop under a proxy domain such as xyz.appspot.com or translate.google.com. Those page views are real page views to a pixel, and they inflate the numbers. Use this filter to add your own patterns to the list of URLs on which the Pixel Manager does not start at all.

info

Available since version 1.27.0.

Each entry is matched as a plain substring against the full URL of the page (window.location.href), so a domain, a host and path, or any recognizable fragment all work. appspot.com and translate.google.com are built in and do not have to be added.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_exclude_domains_from_tracking', function ($domains) {

$domains[] = 'webcache.googleusercontent.com';
$domains[] = 'staging.example.com';

return $domains;
});

When a pattern matches, the Pixel Manager stops before it initializes, so no browser pixel fires and no browser event reaches the Conversion APIs. Server-side purchase events that PHP sends at the end of a checkout are not affected, because they never run in the browser. Use pmw_skip_s2s_purchase_event for those.

warning

The match is a substring of the whole URL, including the query string. A pattern such as de matches almost every URL, so keep the patterns specific.

Block bot user agents from all tracking

The Pixel Manager suppresses tracking for browsers whose user agent identifies a known crawler, which is the reason Googlebot and Google's Merchant Center crawlers cannot fire events on your shop. Use this filter to add patterns of your own.

info

Available since version 1.50.0. The built-in list already covers the search engine crawlers, the AI crawlers, the social preview fetchers, the SEO suites, the common uptime monitors, the headless browsers and the generic HTTP libraries, so most shops never need this filter.

Each entry is matched case-insensitively as a substring of navigator.userAgent.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_exclude_user_agents_from_server_2_server_events', function ($patterns) {

$patterns[] = 'MyMonitoringBot';
$patterns[] = 'InternalHealthCheck';

return $patterns;
});
note

The filter name says server-to-server for historical reasons. A matching user agent is treated exactly like an excluded IP address, which means all browser tracking is suppressed as well, not only the server-to-server events.

Returns whether the Explicit Consent Mode is active, no matter what the setting says. This is the filter to use when the mode has to be on for legal reasons and nobody with access to the settings should be able to switch it off.

info

Available since version 1.42.6.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_consent_management_is_explicit_consent_active', '__return_true');

The mode is then active in addition to the setting, so returning false does not switch it off when the setting has it on. The setting itself is not changed, which means the settings UI keeps showing whatever was saved there.

The filter runs on every request, so a callback that only needs the mode for part of the traffic can decide per request:

/wp-content/themes/child-theme/functions.php
add_filter('pmw_consent_management_is_explicit_consent_active', function ($active) {

// Explicit consent for visitors from the EEA only.
$country = \WC_Geolocation::geolocate_ip()['country'];

return in_array($country, [ 'AT', 'BE', 'DE', 'FR', 'IT', 'NL' ], true);
});

Keep such a callback cheap. It is called on page loads as well as on AJAX requests, so an expensive lookup in it is paid many times over.

Google Analytics debug mode

Turns the debug_mode parameter on for the Google Analytics events, which is what makes them show up in the GA4 DebugView in real time.

info

Available since version 1.32.0. The Measurement Protocol events are Pro.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_enable_ga_4_mp_event_debug_mode', '__return_true');

This covers both transports: the browser events get debug_mode through the data layer, and the server-side Measurement Protocol purchase and refund payloads get it added as an event parameter.

warning

Debug mode is a development tool. Events sent with debug_mode are also processed as regular events, so leave the filter off on a live shop unless you are actively debugging.

Suppress Google Ads remarketing events for variable parents

When the Pixel Manager is set to report variation IDs, a variable product page or product grid that has no variation selected can only report the parent ID. Google Ads then receives an ID that is not in the feed. Return false from this filter to leave those events out instead.

info

Available since version 1.32.0. It replaced wpm_send_events_with_parent_ids, which still works but is deprecated.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_send_events_with_parent_ids', '__return_false');

The scope is narrow on purpose. It only affects the Google Ads dynamic remarketing view_item_list and search events, and only for variable parent products while Output product variations as separate items is on. Every other pixel and every other event is untouched.

note

Google Ads accepts parent IDs as long as they exist in the Merchant Center feed. Check the feed before you switch these events off, because dropping them also drops the remarketing audience signal for those page views.

Opt Meta's Conversion API events out of ads delivery

Sets Meta's opt_out flag on the server-side events, which tells Meta to use them for measurement and attribution but not for ads delivery optimization.

info

Available in Pixel Manager Pro 1.32.0 and later. It replaced wpm_facebook_capi_ads_delivery_opt_out, which still works but is deprecated.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_facebook_capi_ads_delivery_opt_out', '__return_true');

The flag is set on all Conversion API events the Pixel Manager sends, the purchase event included. It is Meta's own documented switch and is sometimes required for shops in regulated verticals.

Turn Meta's Event Setup Tool scan off

Once a day the Pixel Manager reads the Meta signals configuration of every configured pixel and reports the Event Setup Tool rules it finds, because those rules fire events the Pixel Manager has no control over. Use this filter to switch that scan off.

info

Available since version 1.64.0.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_facebook_event_setup_scan_enabled', '__return_false');

The scan is a single cached request per day and it never touches the front end, so switching it off mostly makes sense on a shop whose outgoing requests are locked down. The trade-off is that the Event Setup Tool rules of your pixel are then no longer reported anywhere.

Serve Meta's fbevents.js from a different URL

Replaces the URL of Meta's fbevents.js. Use it to pin the library to a copy you host yourself, or to route it through a proxy of your own.

info

Available since version 1.30.0.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_facebook_fbevents_script_url', function () {
return 'https://cdn.example.com/js/fbevents.js';
});

If all you need is a specific version of Meta's own file, use pmw_facebook_fbevents_script_version instead, which appends the version to Meta's URL. That is the filter the troubleshooting page uses to work around a broken fbevents.js release. The version filter wins when both are set.

warning

A self-hosted copy does not update itself. Meta ships changes to fbevents.js continuously, so a pinned copy drifts and eventually breaks. Treat this as a temporary measure.

Filter the external ID sent to Pinterest

The Pinterest Conversions API takes an external_id, a stable identifier that lets Pinterest tie a shopper's events together across sessions and devices. The Pixel Manager sends the hashed WordPress user ID for a registered customer, and the hashed email address for a guest, since most shops take the majority of their orders from guests.

info

Available in Pixel Manager Pro 1.67.1 and later.

The filter receives the value the Pixel Manager settled on and the full user data object behind the event, so a different identifier can be substituted, or the field can be dropped by returning an empty string.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_pinterest_external_id', function ($external_id, $user_data) {

// Send no external ID at all.
return '';
}, 10, 2);
warning

Pinterest expects this value hashed with SHA-256. If you substitute an identifier of your own, hash it yourself before returning it.

Adjust the arguments of the server-side HTTP requests

Filters the argument array that the Pixel Manager passes to the WordPress HTTP API for the server-side API calls it makes. Use it to raise the timeout on a slow network, to add a header, or to turn TLS verification off in a local environment.

info

Available in Pixel Manager Pro 1.32.0 and later. It replaced wpm_http_post_request_args, which still works but is deprecated.

The filter covers the direct calls to the platform APIs: the Conversion APIs of Meta, TikTok, Pinterest, Snapchat, Reddit, Microsoft, Nextdoor and OpenAI, the Google Analytics Measurement Protocol, and the Mixpanel and Triple Whale APIs. Requests routed through the SweetCode Cloud proxy do not go through this class.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_http_post_request_args', function ($args) {

$args['timeout'] = 10;

return $args;
});

The defaults are a 5 second timeout, HTTP 1.0, non-blocking requests, and TLS verification on everywhere except localhost. What you return is merged over the defaults, so a partial array is enough.

warning

blocking is the one argument to leave alone. The Pixel Manager sends its events non-blocking so a slow platform API cannot slow down a checkout. Setting blocking to true puts the full round trip of every event into the request your customer is waiting on. If you need that while debugging, use pmw_send_all_s2s_requests_blocking below, which exists for exactly that and is easier to find again when you want it gone.

Wait for the platform's response on the server-side requests

Makes the server-side API calls blocking, so the Pixel Manager waits for each platform's response instead of firing the request and moving on. It is a debugging switch, not a setting.

info

Available in Pixel Manager Pro 1.67.1 and later. The filter name existed earlier but had no effect until then.

By default the server-side events go out non-blocking: WordPress hands the request to the network layer and returns immediately, so a platform that answers slowly cannot hold up the page or the checkout the customer is waiting on. The price is that nothing in the shop ever sees the answer. When you are chasing down why a platform is not receiving an event, that is exactly what you need to see.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_send_all_s2s_requests_blocking', '__return_true');

The HTTP request logger already switches the requests to blocking on its own, because it has nothing to write down until the response arrives. Use this filter when you want the blocking behaviour without the logger, for example while stepping through the code with a debugger, or when your own logging sits on the WordPress HTTP API.

warning

Take it out again when you are done. The HTTP request logger switches itself off after three hours for that reason, and this filter has no such safety net. Left in place on a live shop, every purchase adds the round trip to each configured platform API to the time your customer spends waiting on the order confirmation.

Choose the order statuses the reports consider

The order statuses that count as a real sale. WooCommerce's paid statuses plus completed, processing, on-hold and pending. The list decides which orders the lifetime value calculation and the cost of goods coverage scan read.

info

Available since version 1.36.0.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_active_order_statuses', function ($statuses) {

// A shop that parks unpaid orders in a custom status.
$statuses[] = 'awaiting-payment';

// And that never wants pending orders counted.
return array_diff($statuses, [ 'pending' ]);
});

Return the statuses without the wc- prefix. The Pixel Manager adds it where the database queries need it.

Exclude test orders from the lifetime value calculation

Orders placed with one of the email addresses this filter returns are skipped by the lifetime value calculation, so your own test checkouts do not turn up as a returning customer with a lifetime value.

info

Available in Pixel Manager Pro 1.36.0 and later.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_get_test_email_addresses', function ($emails) {

$emails[] = '[email protected]';
$emails[] = '[email protected]';

return $emails;
});

The comparison is against the billing email of the order and it is exact, so list every address you actually test with. The filter applies both to the calculation that runs when an order comes in and to the batch recalculation of the existing orders.

Turn the cost of goods coverage scan off

The Pixel Manager scans recent orders for products that carry no cost of goods, so it can tell you why a profit margin looks wrong. Use this filter to switch that scan off.

info

Available in Pixel Manager Pro 1.67.1 and later.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_cogs_coverage_scan_enabled', '__return_false');

The scan runs in the admin, is cached in a transient, and never touches the front end. Switching it off is worth it on a shop with a very large order table where even the cached scan is noticeable. The profit margin itself keeps working, you just lose the warning about the products that have no cost.

Suppress the plugin's admin notices

Switches the Pixel Manager's own admin notices off, the request for a review among them.

info

Available since version 1.32.0. It replaced wpm_show_admin_notifications, which still works but is deprecated.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_show_admin_notifications', '__return_false');

This is the filter for a shop you hand over to a client, or for an agency that does not want the plugin talking to the shop owner.

Google Tag Gateway operational filters

Four filters for the Google Tag Gateway. The defaults are right for almost every shop. These exist for the cases where they are not.

info

Available since version 1.53.0, except pmw_gtg_handler, which is available since version 1.58.7.

Pin the handler

The Pixel Manager detects the best available gateway handler and caches that decision for 24 hours. Return one of external (the CDN proxy, for example Cloudflare), standalone (the plugin's standalone PHP proxy) or wordpress (routed through WordPress) to skip the detection entirely.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_gtg_handler', function () {
return 'standalone';
});

Any other return value, null included, leaves the detection in charge. This is the filter to reach for when a CDN configuration confuses the detection, or when you want to hold a handler in place while you change something at the CDN. The health check still reports what the pinned handler actually does.

Browser cache duration of the proxied scripts

The proxy tells the browser to cache the Google tag scripts for 6 hours. Lower it while you are debugging, raise it to cut the number of requests that reach your server.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_google_tag_gateway_cache_duration', function ($seconds) {
return 12 * HOUR_IN_SECONDS;
});

The value is in seconds and it applies to the cacheable JavaScript responses only. The measurement requests are never cached.

Timeout of the upstream request

The proxy gives Google 5 seconds to answer before it gives up and the browser falls back to Google's own CDN.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_gtg_proxy_request_timeout', function ($seconds) {
return 8;
});

Raise it on a host with a slow outbound connection. Raising it also means a stuck upstream request occupies a PHP worker for longer, so do not raise it far.

Rate limiting

Rate limiting on the proxy is off by default, because production shops sit behind a CDN that already does it and Google rate limits its own endpoints as well. Switch it on for a shop that has neither.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_gtg_proxy_enable_rate_limiting', '__return_true');

// And, optionally, a different ceiling than the default of 100 requests per minute per IP.
add_filter('pmw_gtg_proxy_rate_limit_max_requests', function ($max_requests, $client_ip) {
return 250;
}, 10, 2);

Both filters also receive the client IP, so an office or monitoring IP can be given its own ceiling.

warning

A ceiling that is too low drops real measurement requests, and a dropped request is a lost conversion. Start high and lower it only with the numbers in front of you.

Settings backup retention

The Pixel Manager keeps automatic backups of its settings so a change can be rolled back. Two filters control how many are kept and how often a new one is created.

How long backups are kept

info

Available since version 1.49.0.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_backup_retention_settings', function ($settings) {

$settings['recent_count'] = 10; // the newest backups to keep, default 5
$settings['daily_retention'] = 30; // days to keep one backup per day, default 14
$settings['monthly_retention'] = 24; // months to keep one backup per month, default 12
$settings['enable_yearly'] = true; // keep one backup per year forever, default true

return $settings;
});

Return all four keys. The retention policy reads each of them by name.

How often a new backup is created

info

Available since version 1.59.0.

Saving a setting creates a backup, and for the next 5 minutes further saves reuse it instead of creating another, so a burst of edits becomes one restore point rather than twenty.

/wp-content/themes/child-theme/functions.php
add_filter('pmw_options_backup_cooldown_seconds', function ($seconds) {
return MINUTE_IN_SECONDS;
});

A shorter window gives you a finer history at the cost of more backups. Returning 0 creates a backup on every single save.

Make more money from your ads with high-precision tracking