Ein Live-Conversion-Dashboard direkt im WP-Admin
Server-seitiges Tracking verlagert den Versand nach PHP, was großartig für die Adblock-Immunität ist und schrecklich für die Sichtbarkeit. Du kannst nicht die DevTools öffnen und einem Server-zu-Server-POST zusehen. Also schreibt Beaconry, was es versendet, in zwei kompakte Speicher in deiner eigenen Datenbank, bewertet jeden Kanal mit 0 bis 10 und mailt dir in dem Moment, in dem das Volumen eines Kanals zusammenbricht oder explodiert. Das Ziel ist einfach: Hör von einem kaputten Pixel aus deinem eigenen WP-Admin, nicht von einem Meta-Mitarbeiter, wenn die Kampagne schon zwei Tage Geld verbrennt.
Das Sichtbarkeits-Loch, das Server-Side aufreißt
Mit einem Browser-Pixel ist Debugging nur einen Network-Tab entfernt. Du klickst auf Kaufen, siehst den Request an die Plattform feuern, liest die Payload, siehst die 200 zurückkommen. Verlagere den Versand server-seitig, und dieses Fenster schließt sich. Die Conversion verlässt deine WordPress-Installation jetzt als Hintergrund-wp_remote_post mit blocking => false, sodass nicht einmal der auslösende PHP-Prozess auf die Antwort wartet. Der Browser des Besuchers ist längst zurückgekehrt. Nichts im Browser hat je mit der Plattform gesprochen.
Genau diese Eigenschaft hast du dir mit Server-Side eingekauft. Sie ist auch der Grund, warum ein kaputter Pixel tagelang unbemerkt bleiben kann. Wenn ein Anbieter still aufhört, deine Events anzunehmen, oder ein Token abläuft, oder ein Caching-Layer das Consent-Cookie frisst, sodass der REST-Endpunkt nie aufgerufen wird, ist das einzige sichtbare Symptom "die Conversions in der Plattform sind auf null gefallen", und das entdeckst du meist erst, wenn jemand fragt, warum die Kampagne nicht mehr optimiert. Beaconrys Antwort darauf: aufzeichnen, was versendet wird, dort wo du es sehen kannst, und dich alarmieren, wenn das Volumen nicht mehr normal aussieht.
Was aufgezeichnet wird und wo
Es gibt einen einzigen Hook, der einmal pro Kanal feuert, direkt nachdem der Versand-Aufruf jedes Kanals zurückkehrt:
do_action( 'bcnr_post_dispatch_event', $channel, $event );Ein Event, das sich auf GA4 und Meta auffächert, feuert das zweimal, einmal pro Kanal, was die korrekte Einheit ist: "wie viele Conversions hat Meta heute gesehen" ist eine Frage pro Kanal. BCNR_Dashboard_Stats lauscht auf dieser Action und schreibt zwei Strukturen in autoload=false-wp-options. Keine neue Datenbank-Tabelle, zwei update_option-Aufrufe pro versendetem Event:
- Der Recent-Ringpuffer (
bcnr_dashboard_recent): die letzten 50 Events über alle Kanäle hinweg. Jeder Eintrag hält den Zeitstempel, den Kanal, den Event-Namen so wie er tatsächlich an den Anbieter gesendet wurde (sodass ein Meta-Hybrid-MappingViewContentzeigt, nicht den internen GA4-Namen), Wert und Währung, die Originalwährung falls Multi-Currency sie umgeschrieben hat, und einen Kontext-String. - Die Zähler pro Kanal und Tag (
bcnr_dashboard_counters): ein Count und eine Wert-Summe pro Kanal pro Tag, 30 Tage lang behalten mit Prune-on-Write, sodass die Option nie unbegrenzt wächst. Das ist die Serie, aus der die Cards, die Sparklines, der Health-Score und der Anomalie-Mailer alle lesen.
Der Kontext-String ist das, was die Tabelle der letzten Conversions lesbar macht statt zu einer Wand aus "page_view". Beaconry löst ihn in Prioritätsreihenfolge auf: ein Formular-Label gewinnt (gesetzt vom Forms-Layer), dann eine Bestellnummer für einen WooCommerce-/EDD-/SureCart-Kauf (gerendert als #1482), und ansonsten der Seitenpfad, von dem das Event kam. Auf einen Blick unterscheidest du einen Kauf auf #1482 von einem Lead über das Kontaktformular von einem Pageview auf /pricing/.
Das ist ein bewusster, dokumentierter Kompromiss bei der ursprünglichen Regel "keine DB-Writes pro Event". Die Begründung ist das Traffic-Profil: eine echte Beaconry-Installation liegt deutlich unter tausend Events pro Stunde, beide Options sind aus dem autoloaded Bundle ausgeschlossen, sodass sie nie einen normalen Page-Load berühren, und eine zweite Migration für eine Dashboard-Tabelle war den Aufwand nicht wert. Zwei Option-Writes pro Event kaufen die gesamte Observability-Fläche.
Das Panel der letzten Conversions
Der Dashboard-Tab liest eine einzige Admin-only-REST-Route:
GET /wp-json/beaconry/v1/dashboard?range=today|7d|30dSie verlangt die manage_options-Capability und einen gültigen wp_rest-Nonce, gesendet als X-WP-Nonce, sodass der Snapshot nie einem ausgeloggten Besucher offengelegt wird. Das Vanilla-JS der Card pollt sie alle 30 Sekunden und pausiert bei visibilitychange, sodass ein im Hintergrund liegender Admin-Tab den Endpunkt nicht hämmert. Kein jQuery, kein Framework, keine Drittanbieter-Charting-Library: die Sparklines sind die Tageszähler, die der Snapshot ohnehin schon trägt.
Das Panel beantwortet die Frage, die DevTools früher für den Browser-Pixel beantwortet haben: "feuert das, was ich konfiguriert habe, tatsächlich, genau jetzt, mit den Werten die ich erwarte?" Du siehst einen Test-Kauf innerhalb eines Poll-Zyklus in der Tabelle landen, du bestätigst, dass Wert und Währung stimmen, du bestätigst, dass er sich auf jeden Kanal aufgefächert hat, den du eingeschaltet hast. Wenn Multi-Currency aktiv ist, siehst du die Conversion als 92.59 EUR (USD), den normalisierten Wert mit annotierter Originalwährung, sodass du prüfen kannst, ob der EZB-Kurs das getan hat, was du wolltest.
Der 0-10-Health-Score
Jede Kanal-Card trägt einen Health-Score, und das Wichtige ist zu verstehen, was er nicht ist. Er ist keine Anbieter-Metrik. Er macht null zusätzliche API-Aufrufe. Er wird vollständig aus derselben WordPress-internen Zähler-Tabelle berechnet, weshalb er günstig genug ist, um bei jedem Snapshot berechnet zu werden. BCNR_Health_Score::for_channel() summiert drei gewichtete Komponenten zu einer Ganzzahl von 0 bis 10:
- Konfiguriert (4 Punkte): hat der Kanal Credentials verdrahtet? Das liest durch genau dieselben
has_*()-Gates, die der Dispatcher nutzt, sodass der Score nie der Live-Konfigurations-Anzeige widersprechen kann. Ein unkonfigurierter Kanal ist nicht "kaputt", er ist einfach nicht fertig, und der Score spiegelt wider, dass du gesagt hast, du willst ihn, aber das Setup nicht abgeschlossen hast. - Aktiv in den letzten 7 Tagen (4 Punkte): mindestens ein versendetes Event in der zurückliegenden Woche. Das ist das mit Abstand nützlichste Signal. Ein konfigurierter Kanal, der sieben Tage lang still war, ist die klassische Form eines kaputten Pixels oder eines Tokens, das der Anbieter still nicht mehr honoriert, die Art von Ausfall, die die Token-Health-Probe nicht immer erwischt, weil das Credential weiterhin gültig aussieht.
- Stabil (2 Punkte): der Variationskoeffizient der 7-Tage-Zähler liegt unter 1,0. Der CoV ist die Standardabweichung geteilt durch den Mittelwert. Unter 1 bedeutet, dass das Tag-zu-Tag-Volumen einigermaßen gleichmäßig ist; über 1 bedeutet, dass einzelne Tage die Serie dominieren, was die Signatur eines intermittierenden Ausfalls ist (ein Caching-Layer, der an Cache-Miss-Tagen Events verliert, ein Consent-Banner, das inkonsistent feuert).
Der Score wird über tier() in einen farbigen Punkt einsortiert: 0 bis 3 ist rot (kaputt oder unkonfiguriert), 4 bis 7 ist gelb (funktioniert, hat aber Probleme), 8 bis 10 ist grün (gesund). Ein konfigurierter Kanal, der stetiges Tagesvolumen feuert, landet bei 10. Ein konfigurierter Kanal, der still geworden ist, fällt auf 4, rot-benachbart, was die Warnung ist, die du willst, bevor die Kampagne aushungert.
Es gibt einen zweiten, einfacheren Indikator neben dem Score: einen Freshness-Status-Punkt, gesteuert davon, wie alt das letzte Event ist. Grün für ein Event innerhalb von 24 Stunden, gelb für 24 bis 72 Stunden, rot für älter als 72 Stunden oder nie. Der Score beantwortet "ist dieser Kanal über eine Woche strukturell gesund"; der Status-Punkt beantwortet "ist kürzlich überhaupt etwas angekommen". Sie sind bewusst getrennte Signale, und ein Kanal mit wenig Traffic kann legitim einen gelben Status-Punkt zeigen, ohne einen schlechten Score zu haben.
Der Anomalie-Mailer: Einbruch heißt kaputt, Anstieg heißt Bots
Das Dashboard ist Pull. Du musst es öffnen. Der Anomalie-Mailer ist Push, und er ist der Teil, der sich seinen Platz verdient, weil niemand am Sonntag um 7 Uhr morgens das Dashboard öffnet, wenn der Pixel kaputtgeht. Ein täglicher Cron (bcnr_anomaly_check) liest die Zähler pro Kanal und beurteilt gestern gegen eine rollierende Baseline. Keine Netzwerk-Aufrufe; es ist reine Arithmetik über Daten, die schon in der Datenbank liegen, weshalb es das falsche Design gewesen wäre, das in die Token-Health-Probe zu falten. Token-grün plus Volumen-rot ist genau das Muster Pixel-kaputt-im-Frontend, das eine Token-Probe nicht sehen kann.
Die Mathematik ist bewusst langweilig, damit sie vorhersehbar ist:
- Baseline: die Summe der sieben Tage vor gestern (Tag 2 bis 8 zurück), geteilt durch 7. Gestern selbst ist aus seiner eigenen Baseline ausgeschlossen, sodass ein Crash die Linie, gegen die er gemessen wird, nicht nach unten zieht.
- Einbruch: der Count von gestern liegt bei oder unter 50 % dieses Durchschnitts. Eine Halbierung des normalen Volumens. Das ist der Alarm "Pixel kaputt": Pixel blockiert oder entfernt, Token abgelaufen, Tag falsch ausgerollt.
- Anstieg: der Count von gestern liegt bei oder über dem 4-Fachen des Durchschnitts. Eine Vervierfachung. Das ist der Alarm "Bots oder Spam": ein geskripteter Formular-Submission-Exploit, eine Bot-Welle oder gelegentlich ein echter viraler Moment (super wenn es so ist, und die Mail sagt das).
- Mindest-Baseline: ein Kanal braucht mindestens 14 Events über das 7-Tage-Fenster, bevor er überhaupt beurteilt wird. Das ist es, was verhindert, dass ein paar Test-Conversions einen Fehlalarm auf einem Kanal auslösen, der kaum feuert.
Wenn ein Kanal eine Schwelle überschreitet, mailt Beaconry an denselben Alert-Empfänger, den auch der Token-Health-Check nutzt. Die Mail nennt den Kanal, den Count von gestern, den Baseline-Durchschnitt und den prozentualen Abstand vom Normalen, dann listet sie die wahrscheinlichen Ursachen für diese Richtung auf (eine Einbruch-Mail spricht über blockierte Pixel und abgelaufene Tokens; eine Anstieg-Mail spricht über Bots und verweist dich auf die Tabelle der letzten Conversions, um die Event-Typen und den Quellkontext zu inspizieren). Ein Transient-Gate pro Kanal und Tag (TTL 23 Stunden, eine Spur unter dem Tagesintervall, sodass der nächste Tag nie blockiert wird) garantiert, dass du höchstens eine Mail pro Kanal pro Tag bekommst, keinen Sturm.
Alle drei Schwellen sind für Power-User filterbar: bcnr_anomaly_drop_ratio, bcnr_anomaly_spike_ratio und bcnr_anomaly_min_baseline. Ein Shop mit hohem Volumen, der schon bei einem sanfteren Rückgang um 30 % alarmiert werden will, kann die Drop-Ratio drehen, ohne Plugin-Code anzufassen.
Warum "zwei Tage später" der ganze Punkt ist
Der Fehlerfall, auf den dieses Design zielt, ist die Latenz der Entdeckung, nicht der Fehler selbst. Pixel gehen kaputt. Tokens laufen ab. Ein Theme-Update ordnet das Consent-Script neu an, und der REST-Endpunkt wird nicht mehr aufgerufen. Das passiert unabhängig davon, welches Tracking-Tool du fährst. Was sich unterscheidet, ist, wie lange die Lücke zwischen "es ist kaputtgegangen" und "du hast es herausgefunden" dauert.
Ohne ein hauseigenes Signal ist der Entdeckungs-Pfad: der Pixel geht kaputt, Conversions kommen nicht mehr bei der Plattform an, der Optimierer der Plattform verliert langsam sein Signal, die Kampagne driftet ab, und irgendwann an Tag zwei oder drei bemerkt ein Mensch die Zahlen und fängt an Fragen zu stellen. Mit den Zählern plus dem Mailer ist der Entdeckungs-Pfad: der Pixel geht kaputt, der Count von heute landet auf null, der Cron am nächsten Morgen sieht gestern auf null gegen eine gesunde Baseline, und du bekommst eine E-Mail, die den Kanal nennt, bevor die Kampagne Zeit zum Abdriften hatte. Derselbe Defekt, eine sehr unterschiedliche Rechnung.
Es lohnt sich, bei der Auflösung ehrlich zu sein. Das ist ein täglicher Cron, der Ganztages-Counts vergleicht, also ist das engste Erkennungsfenster "der Morgen danach". Es ist kein Echtzeit-Pager. Für eine Tracking-Pipeline, die Ad-Plattform-Optimierer füttert, ist der nächste Morgen die richtige Flughöhe: Plattformen aggregieren und attribuieren ohnehin über Tage, also ist es das, was die Ausgaben tatsächlich schützt, einen Null-Tag zu erwischen, bevor er zu einer Null-Woche wird. Wenn du eine Echtzeit-Bestätigung willst, dass ein bestimmter Kanal in dieser Minute feuert, dafür sind das Live-Panel und der End-to-End-Test-Button da; die Aufgabe des Mailers ist die unbeaufsichtigte Frühwarnung.
Fazit
Server-seitiges Tracking tauscht Browser-Sichtbarkeit gegen Adblock-Immunität, und das Dashboard kauft die Sichtbarkeit zurück, ohne die Immunität aufzugeben. Zwei autoload=false-Options zeichnen jeden Versand auf (ein Ringpuffer der letzten 50 für die Live-Tabelle, 30 Tage Zähler pro Kanal für alles andere). Ein 0-10-Score, gebaut aus Konfiguriert, Aktiv-7d und Stabil, ohne Anbieter-Aufrufe, sagt dir, welche Kanäle strukturell gesund sind. Ein täglicher Cron mailt dir bei einem Einbruch um 50 % (kaputt) oder einem Anstieg um das 4-Fache (Bots), gemessen gegen die sieben Tage vor gestern, gedrosselt auf eine Mail pro Kanal pro Tag. Nichts davon ist ein Echtzeit-Pager, und das versucht es auch nicht zu sein. Es ist die Frühwarn-Schicht, die aus "wir haben es zwei Tage später von der Plattform erfahren" ein "Beaconry hat uns am nächsten Morgen gemailt" macht.