Tracking & Attribution

Why Does WP Rocket's Delay JavaScript Setting Break WooCommerce Pixel Tracking?

WP Rocket's Delay JavaScript holds your pixel until the visitor interacts, so WooCommerce events go missing. How it works, what to exclude, and the fix.

Quick answer

WP Rocket's Delay JavaScript setting rewrites your script tags so the browser skips them, then runs them only after the visitor interacts with the page: a key press, a click, a scroll wheel, a mouse move or a touch. A pixel delayed that way fires late or never. A buyer who lands on the order-received page and closes it without touching anything sends no Purchase. Exclude the pixel from the delay, or send Purchase server-side from the paid order.

Tell us what's broken. We'll fix your tracking — free.

Describe the tracking/attribution problem you're stuck on and we'll map it to a fix: server-side conversions to Meta, Google, TikTok and Pinterest, plus first-party tracking that survives Safari. No code required.

WP Rocket’s Delay JavaScript setting breaks WooCommerce pixel tracking because it is built to stop scripts running until the visitor interacts with the page. Your Meta Pixel, TikTok pixel and Pinterest tag are scripts. Delay them, and every event waits for a key press, a click, a scroll or a touch. A visitor who never interacts never fires them.

That is why the symptom reads as “erratic” rather than “broken”. Desktop buyers who nudge the mouse on the thank-you page still send a Purchase. Mobile buyers who glance at the confirmation and close the tab often don’t. Your order count stays steady while Events Manager drifts.

This article explains exactly what the setting does to a script tag, the three ways it loses events, the exclusions that fix the browser side, and why the Purchase itself shouldn’t depend on a browser script running at all.

What does Delay JavaScript actually do to a pixel?

It rewrites the pixel’s script tag so the browser treats it as inert, then reruns it after the first user interaction. WP Rocket changes each script’s type to rocketlazyloadscript, a value browsers don’t execute, and moves the original type to a data-rocket-type attribute. A small loader script waits for interaction and only then turns the delayed scripts back into real ones.

You can see this in WP Rocket’s own source code. The DelayJS/HTML.php class scans the page’s HTML for every script tag. Any tag that doesn’t match an exclusion pattern is rewritten to the inert type. Inline snippets are included, so the fbq('track', 'Purchase', …) call a pixel plugin prints into the page is delayed too, not just the external file.

The loader, lazyload-scripts.min.js, lists the events it waits for: keydown, keyup, mousedown, mouseup, mousemove, mouseover, mouseout, touchmove, touchstart, touchend, touchcancel, wheel, click, dblclick and input. It also listens for visibilitychange, which fires when the tab is hidden or closed.

Mockup of a WooCommerce order-received page passing through WP Rocket's Delay JavaScript: the Meta Pixel script tag rewritten to type rocketlazyloadscript and held at an interaction gate, a desktop visit that moves the mouse firing Purchase, a mobile visit closed without a touch firing nothing, and below both a separate paid-order webhook path sending a server-side Purchase

Why do events go missing instead of just firing late?

Because some visitors never give the page an interaction to wait for, and the rest give it one too late. Events attached to page load, like PageView, ViewContent and the Purchase on the order-received page, only fire after that first interaction. When the visitor leaves before interacting, the script starts too late to send anything, or never starts.

There are three ways an event goes missing.

The no-touch exit. A buyer pays, lands on the order-received page, reads the order number and closes the tab. On a phone that can happen without a single touch. The visibilitychange on close may start the delayed scripts, but the page is already being torn down. Whether the pixel’s network request finishes then is down to timing, not to your setup.

The split snippet. Pixel code usually arrives in two parts: a base script that defines fbq, and inline calls that use it. If an exclusion catches one part but not the other, the order breaks. The event call runs early, fbq doesn’t exist yet, and the browser logs an error instead of an event.

The late timestamp. A delayed PageView fires when the visitor first moves, not when the page loaded. For most reports that’s harmless. For a visitor who lands from an ad and leaves without interacting, it means the visit is never recorded at all, so the ad click has no page view to attach to.

None of this is a WP Rocket bug. Holding scripts until interaction is exactly what the setting promises, and it’s why it lifts PageSpeed scores. The cost lands on anything that needs to run whether or not the visitor touches the page.

How do you check whether Delay JavaScript is delaying your pixel?

View the source of the page where the event should fire and search for rocketlazyloadscript. If your pixel’s script tags carry that type, they are being delayed. Then load the page in a private window, don’t touch anything for ten seconds, and watch the network tab: a delayed pixel sends no request until you move the mouse.

  1. Place a cheap test order and stop on the order-received page.
  2. View the page source and search for fbevents.js (Meta), your TikTok or Pinterest tag, and the inline event calls. Note which ones carry type="rocketlazyloadscript".
  3. Reload the page with the network tab open and keep your hands off the mouse and keyboard. A delayed pixel sends nothing.
  4. Move the mouse once. If the Purchase request appears now, the delay is the cause.
  5. Repeat on a phone, or in mobile emulation, and close the tab without touching it. That’s the buyer you’re losing.

At scale, compare browser Purchase events against paid orders for the week before and the week after you enabled the setting. The guide to what share of WooCommerce buyers never reach the thank-you page walks through the same order-count comparison for gateway redirects.

How do you stop WP Rocket from delaying the pixel?

Add your tracking scripts to WP Rocket’s Delay JavaScript exclusion list, both the external file and the inline calls, then clear the cache and test again. WP Rocket matches each exclusion as a pattern against the whole script tag, so a file name like fbevents.js catches the base script and an escaped call like fbq\( catches the inline events.

Exclude both halves of each pixel. For Meta, that’s fbevents.js and fbq\(. The backslash matters: WP Rocket’s own built-in exclusions write gtag\( the same way, because the pattern is a regular expression and a bare bracket breaks it.

Use the ready-made exclusions where they exist. WP Rocket ships one-click exclusion sets for some tracking plugins. Its entries for Pixel Manager for WooCommerce and Pixel Caffeine carry the note “Fire the tracker on pageload.” That’s WP Rocket’s own answer to this problem.

Check what Safe Mode does and doesn’t cover. Safe Mode excludes jQuery and every script loaded from /wp-content/ and /wp-includes/. A pixel served from the ad platform’s own domain, or printed inline, is still delayed in Safe Mode.

Turn off the delay on checkout if you must. WP Rocket can switch Delay JavaScript off for an individual page through that page’s own options. WooCommerce’s order-received screen is an endpoint of the Checkout page, so set it on Checkout. That keeps the speed gain on product and category pages and protects the page where the Purchase fires.

Clear the cache, then rerun the five-step test. Old optimised copies keep serving delayed tags until they’re purged. The article on how page caching leaves WooCommerce order attribution fields empty covers the cache-side half of the same problem.

The limit is that every one of these fixes still relies on a browser running a script after payment. Ad blockers, closed tabs and payment gateways that never return the buyer break the same Purchase for reasons no exclusion list touches, as the explainer on how ad blockers break conversion tracking shows.

How does PartialLeads keep WooCommerce purchases out of the delay problem?

It doesn’t fire the Purchase from the browser. The PartialLeads WooCommerce plugin sends each order to PartialLeads by webhook once it is paid, meaning processing or completed, and the Purchase goes server-side to Meta, Pinterest and TikTok from there. Nothing fires on the thank-you page, so a delayed or never-run script there can’t lose it.

Paid orders, from the order record. The trigger is the order status, not a page load. Pending, on-hold, failed and cancelled orders aren’t sent. A bank-transfer or cash-on-delivery order is sent when it’s marked paid. The value sent is the full order total, including tax and shipping, after discounts. This is the server-side WooCommerce purchase tracking approach, built in.

Every paid order produces a conversion. Matching it to a person isn’t guaranteed. PartialLeads controls sending the event. Meta, Pinterest and TikTok control whether they can match it to a user and an ad click. The order is matched back to the shopper’s session by visitor id, then email, then phone, then IP, and the identifiers it finds travel with the event. That split is the point of the Conversions API: dispatch stops depending on the browser, while matching still depends on what was captured.

Google Ads works differently. Google Ads purchases are written as rows to a Google Sheet that you import on a schedule. That’s also independent of the thank-you page.

Mockup of the PartialLeads Purchases ledger for a WooCommerce store: paid orders with order number, matched status, source badge and revenue, beside a Meta CAPI activity log showing a server-side Purchase delivered for each paid order with a green status dot and timestamp

Where you see it working. Every paid order appears in the Purchases ledger as matched or unmatched. The Meta CAPI activity log shows the server-side Purchase sent for it, and the Leads list has an API column showing which conversion APIs each lead was sent to. Reconcile a week’s paid WooCommerce orders against those sends. Turning Delay JavaScript on or off doesn’t change that count.

The honest constraints. The PartialLeads plugin’s browser script is still JavaScript. It records the visitor’s landing source, and it sends view product, add to cart and begin checkout, which are forwarded server-side to Meta, Pinterest and TikTok, not Google. Delay it and those events wait for interaction too, so add it to the exclusion list. Keep one source per event: PartialLeads never double-sends, but it doesn’t deduplicate against another plugin’s browser Purchase. If PixelYourSite or Meta for WooCommerce also sends Purchase, switch that one off.

What breaks The mechanism Where you see it in the dashboard
Purchase script delayed until an interaction that never comes Purchase sent server-side from the paid-order webhook, nothing on the thank-you page Meta CAPI activity log, one Purchase per paid order
Mobile buyer closes the order page untouched Order record, not page load, triggers the event Purchases ledger, every paid order listed
Split pixel snippet throws an error No browser Purchase to keep in sync API column in the Leads list
Delayed page view loses the ad click Landing source recorded by the tag once it runs; order matched by visitor id, email, phone or IP Attribution report, first and last touch
Two plugins both send Purchase One source per event, with PartialLeads’ own event ids Meta CAPI activity log alongside Events Manager

Tell us what's broken. We'll fix your tracking — free.

Describe the tracking/attribution problem you're stuck on and we'll map it to a fix: server-side conversions to Meta, Google, TikTok and Pinterest, plus first-party tracking that survives Safari. No code required.

Sources


Frequently asked questions

QDoes WP Rocket's Delay JavaScript break the Facebook pixel?
It delays it, which often looks like breaking it. The setting rewrites the pixel's script tags so the browser skips them, then runs them after the visitor's first key press, click, scroll, mouse move or touch. Visitors who interact still fire events, late. Visitors who leave without interacting never fire them, so PageViews and Purchases go missing unevenly.
QWhat should I add to WP Rocket's Delay JavaScript exclusions for the Meta Pixel?
Exclude both the base script and the inline event calls, for example fbevents.js and fbq\( with the backslash. WP Rocket treats each exclusion as a regular expression matched against the whole script tag, so an unescaped bracket breaks the pattern. Then clear the cache and check the page source for any pixel tag still marked rocketlazyloadscript.
QDoes WP Rocket's Safe Mode stop it delaying my pixel?
Only partly. Safe Mode excludes jQuery and scripts loaded from your site's wp-content and wp-includes folders. A pixel loaded from the ad platform's own domain, or printed inline in the page, is still delayed. Check the page source after enabling it rather than assuming the pixel is covered.
QWill excluding the pixel from Delay JavaScript hurt my PageSpeed score?
Usually a little, because the pixel then loads with the page instead of after interaction. One compromise is to keep the delay site-wide and switch it off only on the Checkout page, which also serves the order-received screen where the Purchase fires. Moving the Purchase server-side removes the trade-off for that event entirely.
QWhy are my Meta purchases lower on mobile since enabling Delay JavaScript?
Mobile buyers often read the order confirmation and close the tab without touching the screen. With the pixel delayed until interaction, that visit gives the script nothing to wait for, so the Purchase either never starts or starts as the page closes and may not finish. Desktop buyers usually move the mouse, which releases the script.
QDoes server-side tracking fix every event Delay JavaScript affects?
No. A server-side Purchase sent from the paid order doesn't depend on any page script. But events that start in the browser, like product views, add to cart and the visitor's landing source, still need a script to run. Keep your tracking scripts out of the delay list even when Purchase is sent server-side.

Find the qualified leads your forms are currently throwing away.

Install PartialLeads on one landing page, send traffic, and compare what your CRM captured against what PartialLeads recovered and qualified.