Skip to main content

JavaScript Events

The Pixel Manager exposes a JavaScript event API on top of jQuery's event system. It works in two directions:

  • Listen to pmw:event:* events to react to everything the Pixel Manager tracks, with the fully processed payload.
  • Trigger a pmw:* event to tell the Pixel Manager that something happened that it could not detect on its own.

Both are supported entry points for your own code and for third party plugins.

Available Since

The pmw:* trigger events have existed for a long time. The pmw:event:* listener API was introduced in version 1.52.1.

Which direction do you need?

You want toUseExample
Send data to another system whenever the Pixel Manager tracks somethingListen to pmw:event:*Push every purchase into your own analytics endpoint
Add a pixel or a conversion the Pixel Manager does not coverListen to pmw:event:*Fire a partner network tag on purchase
Make the Pixel Manager track an interaction it cannot seeTrigger pmw:*A headless or custom-built add-to-cart button
Adjust the data before it reaches a platformNeither, use Event FiltersRewrite the product ID sent to Meta
tip

If you only want to change data that the Pixel Manager already sends, use Event Filters instead. Filters run inside the pipeline and modify the payload. The events on this page run around it.

Listening to events

Listen to pmw:event:<event-name>. The event name is the tracking event with underscores replaced by hyphens, so add_to_cart becomes pmw:event:add-to-cart.

jQuery(document).on("pmw:event:purchase", function (event, payload) {
console.log(payload.event); // "purchase"
console.log(payload.event_data); // the order, product, cart, etc.
console.log(payload.context); // url, referrer, page_type, consent, ...
console.log(payload.pixels); // the data adapted per pixel
console.log(payload.firing); // which pixels fired browser-side and server-side
});

These events fire after the Pixel Manager has processed the event, applied all filters and decided which pixels fire. That makes them the right place to read final, authoritative data.

Available events

Every event the Pixel Manager processes is dispatched:

EventFires when
pmw:event:page-viewA page is viewed
pmw:event:view-itemA product is viewed
pmw:event:view-item-listA product list becomes visible
pmw:event:view-categoryA product category page is viewed
pmw:event:select-itemA product in a list is clicked
pmw:event:searchA search results page is viewed
pmw:event:add-to-cartA product is added to the cart
pmw:event:remove-from-cartA product is removed from the cart
pmw:event:view-cartThe cart is viewed
pmw:event:add-to-wishlistA product is added to a wishlist
pmw:event:begin-checkoutThe checkout starts
pmw:event:add-shipping-infoA shipping method is selected
pmw:event:add-payment-infoA payment method is selected
pmw:event:place-orderThe order button is clicked
pmw:event:purchaseThe purchase confirmation page is reached
pmw:event:loginA customer logs in
pmw:event:account-createdA customer account is created

The payload

KeyContents
eventThe event name in its canonical form, e.g. add_to_cart
event_dataThe core data of the event: product, order, and so on. Empty for events that carry no data of their own
contexttimestamp, url, referrer, user_agent, page_type, user_id and the full consent state
pixelsThe event data adapted to each active pixel's own format
firingPer pixel, whether it fired in the browser and whether it fired server-side

The payload is dispatched regardless of the visitor's consent state, so that your code can make its own decision. payload.context.consent tells you what the visitor allowed:

jQuery(document).on("pmw:event:purchase", function (event, payload) {

// Only act if the visitor accepted marketing cookies
if (!payload.context.consent.categories.marketing) return;

// Your code here
});
warning

If your code sets cookies or sends personal data to a third party, you are responsible for honoring consent yourself. The Pixel Manager only applies consent to its own pixels.

Triggering events

Trigger pmw:<event-name> on document when the Pixel Manager cannot detect an interaction on its own. This is the same entry point the Pixel Manager's own listeners use, so the event goes through the entire pipeline: filters, all active pixels, server-side tracking and consent handling included.

jQuery(document).trigger("pmw:add-to-cart", product);

Available events

EventArgumentNotes
pmw:add-to-cartproduct objectSee Building a product object
pmw:remove-from-cartproduct object
pmw:view-itemproduct object, optional
pmw:view-item-listproduct object, optional
pmw:view-categoryproduct object, optional
pmw:select-itemproduct object
pmw:add-to-wishlistproduct object
pmw:searchnoneReads the search term from the page
pmw:view-cartnone
pmw:begin-checkoutnoneDeduplicated against the Pixel Manager's own checkout triggers
pmw:add-shipping-info{shippingTier: {slug, text}}
pmw:add-payment-info{paymentType: {slug, text}}
pmw:place-ordernone
pmw:purchasenoneReads the order from the data layer
pmw:loginnone
pmw:account-creatednone
caution

Do not trigger pmw:purchase to report an order the Pixel Manager did not already know about. It reads the order from pmwDataLayer.order, which is written by the plugin on the purchase confirmation page, and it does not bypass the order duplication prevention. Reporting purchases from your own code is not a supported path.

Building a product object

The product argument is not free-form. Build it with the Pixel Manager's own helper so it carries every field the pixels expect:

let product = pmw.getProductDetailsFormattedForEvent(productId, quantity);

If the product is not in the data layer yet, because it was never rendered on the page, fetch it from the server first:

if (!pmwDataLayer.products[productId]) {
await pmw.getProductsFromBackend([productId]);
}

Complete example: a custom add-to-cart button

This is how the Pixel Manager's own Doofinder integration works. It listens to the search plugin's event and hands the product to the Pixel Manager:

document.addEventListener("doofinder.cart.add", async function (event) {

const {item_id, amount} = event.detail;

// Make sure the product is in the data layer
if (!pmwDataLayer.products[item_id]) {
await pmw.getProductsFromBackend([item_id]);
}

if (!pmwDataLayer.products[item_id]) return;

const product = pmw.getProductDetailsFormattedForEvent(item_id, amount);

if (!product) return;

jQuery(document).trigger("pmw:add-to-cart", product);
});
info

Trigger the event only for the tracking. If the product was already added to the WooCommerce cart, either by your own code or on the server, do not call pmw.addProductToCart() as well. That would add it a second time in the Pixel Manager's own cart state.

Load order

Your listeners have to be attached before the Pixel Manager fires its events, and your code must not run before pmw exists. Both are solved by the command queue:

window._pmwq = window._pmwq || [];
window._pmwq.push(function () {

jQuery(document).on("pmw:event:add-to-cart", function (event, payload) {
// Your code here
});
});

This works no matter when the Pixel Manager loads, which matters on shops that delay or lazy load JavaScript.

Lifecycle events

Besides the tracking events, the Pixel Manager dispatches a few events about its own state. They fire in this order:

EventFires when
pmw:load-pixelsAll active pixels have been loaded and are about to initialize
pmwLoadThe Pixel Manager finished loading and pmw is available
pmw:readyThe page has finished loading and the Pixel Manager is fully operational

These three are native browser events dispatched on document, so they work with addEventListener as well as with jQuery's .on():

document.addEventListener("pmwLoad", function () {
// pmw is available from here on
});
tip

For your own code, prefer the command queue over pmwLoad. The queue also runs your function when the Pixel Manager loaded before your script did, which pmwLoad does not, because the event has already fired by then.

Debugging

Turn on the console logger by loading any page with ?pmwloggeron. It prints a line for every event that enters and leaves the pipeline, which tells you immediately whether your triggered event arrived:

Pixel Manager: pmw:add-to-cart event fired
Pixel Manager: Processing event: add_to_cart
Pixel Manager: Public event dispatched: pmw:event:add-to-cart

Switch it off again with ?pmwloggeroff.

Stability

The event names and the payload structure on this page are a public API and we keep them stable. Two notes:

  • Internal pmw:pixel:* and pmw:s2s:* events also exist. They are the plumbing between the pipeline and the individual pixels. Do not build on them, they change with the pixel implementations.
  • New keys may be added to the payload. Read the keys you need instead of assuming a fixed shape.

Make more money from your ads with high-precision tracking