Command Queue
The Pixel Manager Command Queue is a powerful asynchronous API that allows developers to safely execute code and interact with the Pixel Manager, regardless of when the Pixel Manager scripts are loaded on the page.
Version 1.49.0 of the Pixel Manager
Why Use the Command Queue?
Modern websites often use optimization techniques like script deferral, lazy loading, or JavaScript bundlers that can delay when scripts are loaded and executed. This creates a timing challenge: your custom code might try to access Pixel Manager functions before they're available, causing errors.
The Command Queue solves this problem by:
- Ensuring execution - Commands are guaranteed to run, whether the Pixel Manager is already loaded or loads later
- Maintaining order - Commands execute in the order they were added to the queue
- Preventing errors - No "undefined" errors from accessing functions before they exist
- Non-blocking - Runs asynchronously without blocking page rendering
How It Works
The Command Queue is a JavaScript array (window._pmwq) that stores functions to be executed. When you add a function to the queue:
- If Pixel Manager is loaded: The function executes immediately
- If Pixel Manager is not loaded yet: The function is stored and executes automatically once Pixel Manager loads
Basic Usage
Single Command
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
// Your code here runs when Pixel Manager is ready
console.log('Pixel Manager is ready!');
});
Multiple Commands
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
console.log('First command');
});
window._pmwq.push(function () {
console.log('Second command');
});
window._pmwq.push(function () {
console.log('Third command');
});
Commands execute in the order they were added (First → Second → Third).
Common Use Cases
1. Using Event Filters
Event filters allow you to modify tracking data before it's sent to advertising platforms. The Command Queue ensures your filters are registered at the right time:
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
// Add a filter to modify purchase data
pmw.hooks.addFilter('pmw_event_payload_purchase', 'my-custom-filter', function (payload) {
// Add 10% to conversion value
payload.event_data.value = payload.event_data.value * 1.1;
return payload;
});
});
See Event Filters for the full list of filter names and the shape of the payload each one receives.
2. Accessing Pixel Manager Functions
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
// Track a custom Facebook event
pmw.trackCustomFacebookEvent('CustomEvent', {
custom_param: 'value',
another_param: 123
});
});
3. Listening to Pixel Manager Events
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
// Listen for add-to-cart events
jQuery(document).on('pmw:add-to-cart', function(event, product) {
console.log('Product added to cart:', product.name);
// Send custom tracking
dataLayer.push({
event: 'custom_add_to_cart',
product_name: product.name,
product_price: product.price
});
});
});
4. Conditional Tracking
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
// Only track for specific user roles
if (pmwDataLayer.user && pmwDataLayer.user.role === 'customer') {
pmw.hooks.addFilter('pmw_event_payload_pre', 'customer-only', function (payload) {
payload.event_data.custom_property = 'customer_value';
return payload;
});
}
});
Using in WordPress (PHP)
You can add Command Queue code through your theme's functions.php or a custom plugin:
Example: Add Custom Event Tracking
add_action('wp_footer', function () {
?>
<script>
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
// Track contact form button clicks
jQuery('.contact-form-submit').on('click', function() {
pmw.trackCustomFacebookEvent('ContactFormClick');
});
});
</script>
<?php
});
Example: Modify Conversion Values
add_action('wp_footer', function () {
?>
<script>
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
// Subtract shipping from conversion value
pmw.hooks.addFilter('pmw_event_payload_purchase', 'exclude-shipping', function (payload) {
if (pmwDataLayer.order) {
payload.event_data.value = payload.event_data.value - pmwDataLayer.order.shipping;
}
return payload;
});
});
</script>
<?php
});
Example: Enhanced Ecommerce Tracking
add_action('wp_footer', function () {
?>
<script>
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
// Send enhanced data to Google Tag Manager
jQuery(document).on('pmw:add-to-cart', function(event, product) {
dataLayer.push({
event: 'enhanced_add_to_cart',
ecommerce: {
currencyCode: product.currency,
add: {
products: [{
name: product.name,
id: product.id,
price: product.price,
brand: product.brand || '',
category: product.category || '',
quantity: product.quantity || 1
}]
}
}
});
});
});
</script>
<?php
});
When Your Command Runs
Queued commands run at one defined point during the Pixel Manager's startup:
- The Pixel Manager loads and reads the data layer.
- The consent module loads and determines the visitor's consent state.
- Your queued commands run.
- The event listeners are registered and the pixels load.
- The first events fire.
Two consequences follow from that position, and both matter:
- The consent state is available. You can read
pmw.consentand call the Consent API at the top level of your command. - Nothing has fired yet. Filters and event listeners you register are in place before the first event, which is the whole reason to use the queue.
Reporting an event from a queued command
Step 3 is before step 4, and that matters if your command does not only listen but also reports an event to the Pixel Manager, for example a pmw:add-to-cart for a custom add-to-cart button, or a pmw:add-shipping-info for a checkout the Pixel Manager cannot read. At that moment the Pixel Manager is not listening to its own entry events yet.
From version 1.66.0 on this is handled: an entry event dispatched from a queued command is held and processed as soon as the listeners and pixels are live. The queue is therefore the right place for it.
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
pmw.bus.emit('pmw:add-to-cart', pmw.getProductDetailsFormattedForEvent(productId, 1));
});
The event was silently dropped: no log line, no pixel, and no error to point at it. On those versions, dispatch the event from a pmwLoad listener instead, which runs after the entry-event listeners exist:
window._pmwq.push(function () {
document.addEventListener('pmwLoad', function () {
jQuery(document).trigger('pmw:add-to-cart', pmw.getProductDetailsFormattedForEvent(productId, 1));
});
});
This applies to reporting events only. Registering listeners and filters, which is what most commands do, has always belonged in the queue and is unaffected. Full details in JavaScript Events.
Step 2 and step 3 used to be the other way round: queued commands ran before the consent module had loaded, so pmw.consent did not exist yet.
Reading it at the top level of a queued command therefore threw an error, and because queued commands are wrapped in a try/catch (see below), the failure was silent and every line after the consent check was skipped, typically including the registration of your own event listeners.
If you need to support version 1.64.0 or older, do the consent check inside your event handler rather than at the top level of the command:
window._pmwq.push(function () {
jQuery(document).on('pmw:event:purchase', function (event, payload) {
// Available here on every version. The event payload also carries the
// consent state directly, so no lookup is needed at all:
if (!payload.context.consent.categories.marketing) return;
});
});
Register listeners immediately inside your command, not after an await or inside a .then() callback. If your command waits for something first, for example loading a third-party script of your own, the Pixel Manager's events can fire before your listener exists.
This matters most for the purchase event. It fires once per order and is then locked out permanently, on a page reload included, so an integration that registers its purchase listener too late loses the conversion with no second chance.
// Correct: register first, then load whatever you need inside the handler
window._pmwq.push(function () {
pmw.bus.on('pmw:event:purchase', function (payload) {
pmw.loadScriptAndCacheIt('https://example.com/tag.js').then(function () {
// report the conversion
});
});
});
// Wrong: the purchase event can fire while the script is still downloading
window._pmwq.push(function () {
pmw.loadScriptAndCacheIt('https://example.com/tag.js').then(function () {
pmw.bus.on('pmw:event:purchase', function (payload) { /* may never run */ });
});
});
pmw.bus is available from version 1.65.0. On older versions use jQuery(document).on('pmw:event:purchase', function (event, payload) { … }), which keeps working on every version.
From version 1.65.0 a purchase listener registered through pmw.bus.on() also receives the order when it registers after the event has already fired, which makes even the second form above work. Registering synchronously remains the recommended pattern: it is the only one that is also safe with jQuery(document).on(), and on older versions it is the only one that works at all.
Each queued command runs inside a try/catch, so one broken command cannot stop the Pixel Manager or any other command. The trade-off is that a failure is quiet: the error goes to the browser console and everything after the failing line in that command is skipped. If part of your integration mysteriously does nothing, open the browser console and look for:
Pixel Manager: Error executing queued command
The message includes the beginning of the command's source, so you can tell which snippet failed.
Available Pixel Manager Functions
Inside the Command Queue you have access to the Pixel Manager API, including the consent state:
Event Tracking Functions
// Track custom Facebook events
pmw.trackCustomFacebookEvent(eventName, customData);
// Access the console logger (if enabled)
pmw.console.log(message, data);
Filter and Hook System
// Add a filter
pmw.hooks.addFilter(hookName, namespace, callback, priority);
// Add an action
pmw.hooks.addAction(hookName, namespace, callback, priority);
// Remove a filter
pmw.hooks.removeFilter(hookName, namespace);
// Remove an action
pmw.hooks.removeAction(hookName, namespace);
Consent State
// Read the visitor's consent categories
pmw.consent.categories.get(); // { statistics, marketing, preferences, necessary }
// Drive the consent state from a custom cookie banner
pmw.consent.api.acceptAll();
Full reference: Consent API.
Data Access
// Access the data layer
console.log(pmwDataLayer);
// Access specific data
if (pmwDataLayer.shop) {
console.log('Currency:', pmwDataLayer.shop.currency);
}
if (pmwDataLayer.order) {
console.log('Order ID:', pmwDataLayer.order.id);
}
Event Reference
Public API Events (Recommended)
The pmw:event:* namespace is the official public API for third-party integrations. These events provide the fully processed payload including all pixel-specific data and consent status.
Listen to these events to receive complete, processed event data:
pmw:event:page-view- Page view with full contextpmw:event:view-item- Product page viewedpmw:event:view-item-list- Product list/category viewedpmw:event:select-item- Product clicked/selectedpmw:event:add-to-cart- Product added to cartpmw:event:remove-from-cart- Product removed from cartpmw:event:view-cart- Cart page viewedpmw:event:begin-checkout- Checkout startedpmw:event:add-payment-info- Payment method selectedpmw:event:add-shipping-info- Shipping method selectedpmw:event:purchase- Order completedpmw:event:add-to-wishlist- Product added to wishlistpmw:event:search- Search performedpmw:event:account-created- New account created (coming in v1.56.1)
Example:
window._pmwq = window._pmwq || [];
window._pmwq.push(function() {
jQuery(document).on('pmw:event:add-to-cart', function(event, payload) {
console.log('Add to cart event:', payload);
console.log('Event name:', payload.event);
console.log('Product data:', payload.event_data);
console.log('Pixel-specific data:', payload.pixels);
});
});
Entry Point Events
These are the events you dispatch to the Pixel Manager to report something it cannot detect on its own. They are also the events its own listeners use internally, so listening to them shows you the raw interaction before it is processed:
pmw:page-view- Page viewpmw:view-item- Product page viewedpmw:view-category- Category page viewedpmw:search- Search performedpmw:add-to-cart- Product added to cartpmw:remove-from-cart- Product removed from cartpmw:select-item- Product clicked/selectedpmw:add-to-wishlist- Product added to wishlistpmw:begin-checkout- Checkout startedpmw:add-payment-info- Payment method selectedpmw:place-order- Order placement initiatedpmw:purchase- Order completedpmw:login- User logged inpmw:account-created- New account created (coming in v1.56.1)
pmw:event:*events contain the fully processed payload with all pixel adaptations and firing decisionspmw:*events are entry point events with raw event data before processing
To listen, prefer pmw:event:*: it carries the complete information. To report an interaction to the Pixel Manager, use the pmw:* entry event. See JavaScript Events.
Troubleshooting
Command Not Executing
Problem: Your command doesn't seem to run.
Solution: Enable the Console Logger to verify when Pixel Manager loads:
window._pmwq = window._pmwq || [];
window._pmwq.push(function () {
console.log('This message confirms the command executed');
});
Command Stops Halfway
Problem: The first part of your command clearly runs, but the rest does nothing. Typically your event listener is never called, or your integration reports no conversions while everything else on the page works.
Solution: Your command threw an error, which the queue caught and logged. Open the browser console on the affected page and look for Pixel Manager: Error executing queued command. The message names the error and shows the beginning of the command, and everything after the failing line was skipped.
The usual causes are a typo in a Pixel Manager function name and a reference to a variable that does not exist yet on that page type, for example reading pmwDataLayer.order outside the order confirmation page.
Missing Purchase Conversions
Problem: Your integration reports page views or clicks, but never a sale.
Solution: Check that the purchase listener is registered synchronously inside your command, not after an await, a .then() or any other wait. See When Your Command Runs. Confirm the event reaches your code at all by adding a listener that only logs:
window._pmwq.push(function () {
pmw.bus.on('pmw:event:purchase', function (payload) {
console.log('purchase received', payload);
});
});
Function Not Found
Problem: pmw.someFunction is not a function error.
Solution: Verify you're calling functions that exist in the Pixel Manager API. Check the Event Filters documentation for available functions.
Best Practices
-
Always initialize the queue first
window._pmwq = window._pmwq || []; -
Keep commands focused - One command should do one thing
// Goodwindow._pmwq.push(function() {pmw.hooks.addFilter('pmw_event_payload_pre', 'my-filter', callback);});// Avoid mixing unrelated operations in one command -
Use meaningful namespace identifiers in filters
pmw.hooks.addFilter('pmw_event_payload_purchase', 'my-shop-exclude-shipping', callback);// Not: pmw.hooks.addFilter('pmw_event_payload_purchase', 'filter1', callback); -
Register event listeners synchronously - Never behind an
awaitor a.then(), or the event can fire before your listener exists -
Handle errors gracefully
window._pmwq.push(function() {try {// Your code} catch(e) {console.error('Error:', e);}}); -
Test with Console Logger enabled - Use
?pmwloggeronto verify your code runs correctly
Related Documentation
- Integrate a Third-Party Conversion Tag - The complete pattern for affiliate networks and other external tags
- Event Filters - Modify tracking data with filters and hooks
- Console Logger - Debug your Command Queue implementations
- Tips and Tricks - More code examples and patterns
- PHP Filters - Server-side WordPress/WooCommerce filters