Cache-plugin compatibility
A JavaScript optimizer that delays, combines or async-rewrites Beaconry's tracking script will silently stop your pageview from firing. Beaconry auto-excludes itself from the four optimizers that expose a documented opt-out (WP Rocket, LiteSpeed, SG Optimizer, Cloudflare Rocket Loader), so for most stacks there is nothing to configure. Two optimizer features have no code-level marker and need one checkbox each. Plain page caching is always safe.
Why JS optimization breaks tracking
Beaconry loads two pieces on the front end: the deferred nl-data.js file (plus the consent banner script), and a small inline block that calls NLData.init(). That inline block is what actually fires the pageview, and it carries the per-request security nonce the REST endpoint checks. Three classes of "speed" optimization interfere with that:
- Delay JavaScript Execution (WP Rocket Delay-JS, LiteSpeed Delay, SG Optimizer's defer). These hold all JavaScript until the first user interaction (scroll, tap, mouse move). A visitor who reads a page and leaves without interacting never runs
NLData.init(), so the pageview, and every event that depends on it, never fires. This is the single most damaging one, because it looks like Beaconry "randomly" loses traffic. - Combine JavaScript. Merging the inline init into one big bundle can reorder it relative to the deferred file it depends on, so
NLDatais called before it exists. - Async rewriting / Rocket Loader. Cloudflare Rocket Loader rewrites script tags to load asynchronously through its own loader, which again breaks the load order between the file and the inline init.
Plain minification (whitespace stripping) does not break execution order and is safe. The problem is always defer/delay, combine, or async rewriting, not minify.
The two surfaces, and why they need different fixes
This is the detail that trips up hand-rolled exclude lists. WordPress emits Beaconry as two separate tags: the external <script src="...nl-data.js"> and a separate inline <script> (the NLData.init() block). The standard WordPress filter for tagging a script, script_loader_tag, only ever rewrites the external file tag. It cannot touch the inline block. So protecting only the file is not enough, the inline init has to be excluded by content as well, through a different mechanism. Beaconry handles both. A manual exclude that only lists the file URL would still lose the pageview.
What Beaconry auto-excludes (no setup)
On every front-end load, Beaconry registers exclusion filters and tag attributes for the optimizers that publish a documented, code-level opt-out. Each marker below was verified verbatim against that vendor's own documentation, not a blog or a forum thread. If you run one of these plugins, you do not have to configure anything.
| Optimizer | Feature covered | How Beaconry opts out | Surface |
|---|---|---|---|
| Cloudflare | Rocket Loader | data-cfasync="false" on the tag | External file |
| WP Rocket | Delay JavaScript Execution | nowprocket attribute on the tag | External file |
| WP Rocket | Defer / Delay (inline) | rocket_defer_inline_exclusions filter | Inline init |
| LiteSpeed Cache | Combine + Minify | litespeed_optimize_js_excludes filter | Script handle |
| LiteSpeed Cache | Defer + Delay | litespeed_optm_js_defer_exc filter | Script handle |
| LiteSpeed Cache | Guest Mode JS | litespeed_optm_gm_js_exc filter | Script handle |
| SG Optimizer | Async / Defer | sgo_js_async_exclude filter | Script handle |
| SG Optimizer | Minify | sgo_js_minify_exclude filter | Script handle |
| SG Optimizer | Combine (file) | sgo_javascript_combine_exclude filter | Script handle |
| SG Optimizer | Combine (inline) | sgo_javascript_combine_excluded_inline_content filter | Inline init |
A few implementation notes worth knowing:
- Cloudflare requires
data-cfasync="false"to appear before thesrcattribute, so Beaconry injects it at the front of the tag. The attribute is added idempotently, if another plugin already marked the tag, Beaconry leaves it alone. - LiteSpeed and SG Optimizer work off WordPress script handles, so Beaconry adds its two handles (
bcnr-nl-dataandbcnr-nl-data-gate) to each list. That one handle list covers combine, minify, defer, delay and (on LiteSpeed) Guest Mode in a single shot. - The inline init is excluded by a stable content substring (
NLData.init) on the two optimizers that expose an inline-exclude filter (WP Rocket and SG Optimizer), which is what keeps the pageview-firing block out of defer and combine.
Two manual cases (one checkbox each)
Two optimizer features genuinely have no documented code-level opt-out, so Beaconry cannot auto-apply them. If you turn either feature on, add the exclusion by hand in the plugin's admin UI. Both are quick.
WP Rocket: Combine JavaScript
WP Rocket's Combine JavaScript has no filter or attribute to exclude a file or an inline snippet, only the admin-UI fields. Under WP Rocket → File Optimization, add two entries:
- Excluded JavaScript Files: add
nl-data.js(the path fragment is enough, it matches Beaconry's bundled file). - Excluded Inline JavaScript: add
NLData.initso the pageview-firing inline block is kept out of the combined bundle.
Context, so you can judge whether you even need this: Combine JS is legacy and off by default on HTTP/2 sites (combining hurts more than it helps over a multiplexed connection). The WP Rocket feature that actually breaks tracking in practice is Delay JavaScript Execution, and that one is already auto-excluded for you via the nowprocket attribute. So unless you deliberately turned Combine on, there is nothing to do here.
Cloudflare: Auto-Minify and APO combine
Cloudflare's legacy Auto-Minify and the JS-combine that ships with APO are zone-level dashboard toggles (Speed → Optimization) with no per-script origin marker, so an origin-side attribute like data-cfasync cannot reach them. The good news: minify alone does not break execution order, it only strips whitespace, so it is safe to leave on. The only Cloudflare JS optimizer that reorders execution is Rocket Loader, and Rocket Loader is auto-excluded via data-cfasync="false". In short: keep Rocket Loader off (or rely on Beaconry's auto-exclude), and you can leave Auto-Minify on without affecting tracking. There is no manual checkbox needed for Cloudflare, this case is here so you do not go hunting for a problem that is not there.
Plain page caching is always safe
Page caching (serving a stored HTML copy of the page) is a different thing from JavaScript optimization, and it does not need any exclusion. WP Super Cache, the page-cache layer of W3 Total Cache or WP Fastest Cache, Cloudflare's edge HTML cache, all of these are safe with Beaconry out of the box.
The one thing that could have broken with cached HTML is the security nonce. Every page embeds a short-lived WordPress nonce in the inline config; the REST endpoint rejects events whose nonce has expired. WordPress nonces rotate roughly every 12 hours and stay valid for about 24, so a page served from cache (or a tab left open overnight) could eventually carry a nonce the endpoint refuses, and silently drop every event. Beaconry closes that gap on the client side:
- Before sending an event,
nl-data.jschecks how long the page has been alive. If it is older than 6 hours, it fetches a fresh nonce from a dedicated/wp-json/beaconry/v1/nonceroute (with the visitor's own cookies, so the new nonce matches their session) and uses that for the send. - That nonce route is marked non-cacheable, both with a
no-storeheader and with an explicit LiteSpeed no-cache signal, so no proxy or cache plugin can freeze a soon-to-expire nonce and hand it back. - If the refresh fetch fails for any reason, it falls back to the existing nonce rather than blocking the event. WordPress's own 12-to-24-hour validity tolerance covers the gap, which comfortably spans typical cache TTLs.
Because this is vendor-independent and runs in the browser, it works the same regardless of which page-cache plugin (if any) is in front of the site. A long-open page, a stale cached page, or a rotated guest session all keep tracking.
Quick decision guide
| Your stack | What to do |
|---|---|
| WP Rocket, Delay-JS on (default) | Nothing. Auto-excluded. |
| WP Rocket, Combine JS on | Add nl-data.js + NLData.init in File Optimization (the two manual fields above). |
| LiteSpeed Cache (any JS optimization) | Nothing. Handle excludes cover combine, minify, defer, delay, Guest Mode. |
| SG Optimizer (any JS optimization) | Nothing. Handle + inline excludes cover async, minify, combine. |
| Cloudflare Rocket Loader | Nothing. Auto-excluded via data-cfasync="false". |
| Cloudflare Auto-Minify / APO minify | Nothing. Minify does not break execution order. |
| Page caching of any kind | Nothing. Client-side nonce refresh keeps cached pages tracking. |
| Another optimizer with aggressive JS-combine | Exclude nl-data.js and the NLData.init inline snippet from its JS optimization. Page-cache mode alone is always safe. |
How to confirm it is working
The fastest check is the Beaconry Live Dashboard: load a page on the front end (as a logged-out visitor, since logged-in admins are excluded from tracking by default), then watch the Live-Conversions panel for the pageview. If events arrive, optimization is not interfering. If nothing shows up on a site with one of the delay/combine features on, open DevTools and confirm the NLData.init inline block actually executed, a Delay-JS optimizer that is still holding it is the usual culprit. The troubleshooting guide walks through the rest.