Kompatibilität mit Cache-Plugins
Ein JavaScript-Optimizer, der Beaconrys Tracking-Script verzögert, kombiniert oder async umschreibt, sorgt still dafür, dass dein Pageview nicht mehr feuert. Beaconry schließt sich automatisch von den vier Optimizern aus, die ein dokumentiertes Opt-out anbieten (WP Rocket, LiteSpeed, SG Optimizer, Cloudflare Rocket Loader), bei den meisten Stacks gibt es also nichts zu konfigurieren. Zwei Optimizer-Features haben keinen Marker auf Code-Ebene und brauchen je eine Checkbox. Reines Page-Caching ist immer sicher.
Warum JS-Optimierung das Tracking bricht
Beaconry lädt zwei Teile im Front-End: die deferred nl-data.js-Datei (plus das Consent-Banner-Script) und einen kleinen Inline-Block, der NLData.init() aufruft. Genau dieser Inline-Block feuert tatsächlich den Pageview, und er trägt die Per-Request-Security-Nonce, die der REST-Endpoint prüft. Drei Klassen von "Speed"-Optimierung kommen sich damit in die Quere:
- Delay JavaScript Execution (WP Rocket Delay-JS, LiteSpeed Delay, der Defer von SG Optimizer). Diese halten sämtliches JavaScript bis zur ersten Nutzer-Interaktion zurück (Scroll, Tap, Mausbewegung). Ein Besucher, der eine Seite liest und ohne Interaktion wieder geht, führt
NLData.init()nie aus, also feuert der Pageview, und jedes davon abhängige Event, nie. Das ist die mit Abstand schädlichste, weil es so aussieht, als würde Beaconry "zufällig" Traffic verlieren. - Combine JavaScript. Wird die Inline-Init in ein großes Bundle gemerged, kann sie relativ zu der deferred Datei, von der sie abhängt, umsortiert werden, sodass
NLDataaufgerufen wird, bevor es existiert. - Async-Rewriting / Rocket Loader. Cloudflare Rocket Loader schreibt Script-Tags so um, dass sie asynchron über seinen eigenen Loader geladen werden, was erneut die Ladereihenfolge zwischen Datei und Inline-Init bricht.
Reine Minification (Whitespace-Stripping) bricht die Ausführungsreihenfolge nicht und ist sicher. Das Problem ist immer Defer/Delay, Combine oder Async-Rewriting, nicht Minify.
Die zwei Surfaces, und warum sie unterschiedliche Fixes brauchen
Das ist das Detail, an dem handgestrickte Ausschluss-Listen scheitern. WordPress gibt Beaconry als zwei separate Tags aus: die externe <script src="...nl-data.js"> und ein separates Inline-<script> (der NLData.init()-Block). Der Standard-WordPress-Filter zum Taggen eines Scripts, script_loader_tag, schreibt immer nur das Tag der externen Datei um. Den Inline-Block kann er nicht anfassen. Nur die Datei zu schützen reicht also nicht, die Inline-Init muss zusätzlich nach Inhalt ausgeschlossen werden, über einen anderen Mechanismus. Beaconry deckt beides ab. Ein manueller Ausschluss, der nur die Datei-URL listet, würde den Pageview trotzdem verlieren.
Was Beaconry automatisch ausschließt (ohne Setup)
Bei jedem Front-End-Load registriert Beaconry Ausschluss-Filter und Tag-Attribute für die Optimizer, die ein dokumentiertes Opt-out auf Code-Ebene veröffentlichen. Jeder Marker unten wurde wortwörtlich gegen die eigene Dokumentation des jeweiligen Anbieters verifiziert, nicht gegen einen Blog oder Forenthread. Wenn du eines dieser Plugins betreibst, musst du nichts konfigurieren.
| Optimizer | Abgedecktes Feature | Wie Beaconry sich ausschließt | Surface |
|---|---|---|---|
| Cloudflare | Rocket Loader | data-cfasync="false" am Tag | Externe Datei |
| WP Rocket | Delay JavaScript Execution | nowprocket-Attribut am Tag | Externe Datei |
| 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 (Datei) | sgo_javascript_combine_exclude-Filter | Script-Handle |
| SG Optimizer | Combine (inline) | sgo_javascript_combine_excluded_inline_content-Filter | Inline-Init |
Ein paar Implementierungs-Notizen, die man kennen sollte:
- Cloudflare verlangt, dass
data-cfasync="false"vor demsrc-Attribut steht, deshalb injiziert Beaconry es am Anfang des Tags. Das Attribut wird idempotent hinzugefügt, hat ein anderes Plugin das Tag bereits markiert, lässt Beaconry es in Ruhe. - LiteSpeed und SG Optimizer arbeiten über WordPress-Script-Handles, deshalb fügt Beaconry seine zwei Handles (
bcnr-nl-dataundbcnr-nl-data-gate) jeder Liste hinzu. Diese eine Handle-Liste deckt Combine, Minify, Defer, Delay und (bei LiteSpeed) Guest Mode in einem Rutsch ab. - Die Inline-Init wird über einen stabilen Inhalts-Substring (
NLData.init) bei den zwei Optimizern ausgeschlossen, die einen Inline-Ausschluss-Filter anbieten (WP Rocket und SG Optimizer), und genau das hält den pageview-feuernden Block aus Defer und Combine heraus.
Zwei manuelle Fälle (je eine Checkbox)
Zwei Optimizer-Features haben echt kein dokumentiertes Opt-out auf Code-Ebene, also kann Beaconry sie nicht automatisch anwenden. Wenn du eines der beiden Features einschaltest, trage den Ausschluss von Hand in der Admin-UI des Plugins ein. Beide gehen schnell.
WP Rocket: Combine JavaScript
WP Rockets Combine JavaScript hat keinen Filter und kein Attribut, um eine Datei oder ein Inline-Snippet auszuschließen, nur die Admin-UI-Felder. Unter WP Rocket → File Optimization trägst du zwei Einträge ein:
- Excluded JavaScript Files:
nl-data.jshinzufügen (das Pfad-Fragment reicht, es matcht Beaconrys gebündelte Datei). - Excluded Inline JavaScript:
NLData.inithinzufügen, damit der pageview-feuernde Inline-Block aus dem kombinierten Bundle herausgehalten wird.
Kontext, damit du beurteilen kannst, ob du das überhaupt brauchst: Combine JS ist Legacy und auf HTTP/2-Sites standardmäßig aus (Kombinieren schadet über eine multiplexte Verbindung mehr, als es nützt). Das WP-Rocket-Feature, das in der Praxis tatsächlich das Tracking bricht, ist Delay JavaScript Execution, und das ist über das nowprocket-Attribut bereits automatisch für dich ausgeschlossen. Solange du Combine also nicht bewusst eingeschaltet hast, gibt es hier nichts zu tun.
Cloudflare: Auto-Minify und APO-Combine
Cloudflares Legacy-Auto-Minify und das JS-Combine, das mit APO kommt, sind Zonen-Level-Dashboard-Toggles (Speed → Optimization) ohne Per-Script-Origin-Marker, ein Origin-seitiges Attribut wie data-cfasync erreicht sie also nicht. Die gute Nachricht: Minify allein bricht die Ausführungsreihenfolge nicht, es strippt nur Whitespace, also ist es sicher, es anzulassen. Der einzige Cloudflare-JS-Optimizer, der die Ausführung umsortiert, ist Rocket Loader, und Rocket Loader wird über data-cfasync="false" automatisch ausgeschlossen. Kurz: Rocket Loader aus lassen (oder auf Beaconrys Auto-Ausschluss vertrauen), und du kannst Auto-Minify anlassen, ohne das Tracking zu beeinträchtigen. Für Cloudflare ist keine manuelle Checkbox nötig, dieser Fall steht hier, damit du nicht nach einem Problem suchst, das es gar nicht gibt.
Reines Page-Caching ist immer sicher
Page-Caching (das Ausliefern einer gespeicherten HTML-Kopie der Seite) ist etwas anderes als JavaScript-Optimierung und braucht keinen Ausschluss. WP Super Cache, die Page-Cache-Schicht von W3 Total Cache oder WP Fastest Cache, Cloudflares Edge-HTML-Cache, all das ist mit Beaconry out of the box sicher.
Das Einzige, was mit gecachtem HTML brechen könnte, ist die Security-Nonce. Jede Seite bettet eine kurzlebige WordPress-Nonce in die Inline-Config ein, der REST-Endpoint lehnt Events ab, deren Nonce abgelaufen ist. WordPress-Nonces rotieren etwa alle 12 Stunden und bleiben rund 24 Stunden gültig, eine aus dem Cache ausgelieferte Seite (oder ein über Nacht offen gelassener Tab) könnte also irgendwann eine Nonce tragen, die der Endpoint verweigert, und still jedes Event verwerfen. Beaconry schließt diese Lücke auf der Client-Seite:
- Bevor ein Event gesendet wird, prüft
nl-data.js, wie lange die Seite schon lebt. Ist sie älter als 6 Stunden, holt es eine frische Nonce von einer dedizierten/wp-json/beaconry/v1/nonce-Route (mit den eigenen Cookies des Besuchers, damit die neue Nonce zu seiner Session passt) und verwendet diese fürs Senden. - Diese Nonce-Route ist als nicht cachebar markiert, sowohl mit einem
no-store-Header als auch mit einem expliziten LiteSpeed-No-Cache-Signal, sodass kein Proxy und kein Cache-Plugin eine bald ablaufende Nonce einfrieren und zurückgeben kann. - Schlägt der Refresh-Fetch aus irgendeinem Grund fehl, fällt es auf die bestehende Nonce zurück, statt das Event zu blockieren. WordPress' eigene 12-bis-24-Stunden-Gültigkeitstoleranz deckt die Lücke ab, was typische Cache-TTLs locker überspannt.
Weil das anbieterunabhängig ist und im Browser läuft, funktioniert es gleich, egal welches Page-Cache-Plugin (falls überhaupt) vor der Site sitzt. Eine lange offene Seite, eine veraltete gecachte Seite oder eine rotierte Gast-Session, alle tracken weiter.
Schneller Entscheidungs-Guide
| Dein Stack | Was zu tun ist |
|---|---|
| WP Rocket, Delay-JS an (Standard) | Nichts. Automatisch ausgeschlossen. |
| WP Rocket, Combine JS an | nl-data.js + NLData.init in File Optimization eintragen (die zwei manuellen Felder oben). |
| LiteSpeed Cache (beliebige JS-Optimierung) | Nichts. Handle-Ausschlüsse decken Combine, Minify, Defer, Delay, Guest Mode ab. |
| SG Optimizer (beliebige JS-Optimierung) | Nichts. Handle- + Inline-Ausschlüsse decken Async, Minify, Combine ab. |
| Cloudflare Rocket Loader | Nichts. Automatisch ausgeschlossen über data-cfasync="false". |
| Cloudflare Auto-Minify / APO-Minify | Nichts. Minify bricht die Ausführungsreihenfolge nicht. |
| Page-Caching jeder Art | Nichts. Client-seitiger Nonce-Refresh hält gecachte Seiten am Tracken. |
| Anderer Optimizer mit aggressivem JS-Combine | nl-data.js und das NLData.init-Inline-Snippet von seiner JS-Optimierung ausschließen. Reiner Page-Cache-Modus allein ist immer sicher. |
Wie du prüfst, dass es funktioniert
Der schnellste Check ist das Beaconry Live Dashboard: lade eine Seite im Front-End (als ausgeloggter Besucher, da eingeloggte Admins standardmäßig vom Tracking ausgeschlossen sind), dann beobachte im Live-Conversions-Panel den Pageview. Kommen Events an, stört keine Optimierung. Taucht auf einer Site mit aktivem Delay-/Combine-Feature nichts auf, öffne die DevTools und bestätige, dass der NLData.init-Inline-Block tatsächlich ausgeführt wurde, ein Delay-JS-Optimizer, der ihn noch zurückhält, ist der übliche Übeltäter. Der Troubleshooting-Guide führt durch den Rest.