Conversions auf jedem Button auslösen, mit einer CSS-Klasse
Die meisten Conversions auf einer Site sind keine Formular-Submits oder WooCommerce-Bestellungen. Es sind Klicks: ein Kaufen-Button, der einen externen Checkout öffnet, ein Kontakt-CTA, der zu einer Telefonnummer scrollt, ein Pricing-Page-Link, der zu Polar oder Stripe weiterreicht. Beaconry deckt die mit fünf generischen CSS-Slots ab. Füge eine Klasse zum Element hinzu, und der Klick feuert eine server-seitige Conversion durch dieselbe Pipeline wie alles andere. Kein JavaScript zu schreiben, kein Vendor-Snippet zum Einfügen.
Die Lücke zwischen Formular-Hooks und Commerce-Hooks
Beaconry hat tiefe server-seitige Abdeckung dort, wo es die Plattform direkt hooken kann. Formular-Plugins feuern ein lead, wenn ein Submit in PHP landet. WooCommerce, EDD und SureCart feuern einen Zehn-Event-Funnel aus echten Order-Hooks. Diese Pfade sind präzise, weil die Daten genau dort auf dem Server liegen: die Formularfelder, der Bestellwert, die Line Items.
Aber viel hochwertige Intent erreicht nie einen Server-Hook auf deiner Site. Ein Button, der buy.polar.sh in einem neuen Tab öffnet, navigiert weg, bevor irgendein PHP läuft. Ein "Termin buchen"-Link, der auf Calendly zeigt, verlässt deine Domain komplett. Ein "Testversion herunterladen"-Anker löst eine Datei-Response aus, keinen Formular-Submit. Da ist kein Submit, keine Bestellung, kein Hook zum Lauschen. Das einzige Signal ist der Klick selbst, im Browser, in dem Moment, in dem er passiert.
Click-Tracking füllt genau diese Lücke. Es ist ein browser-seitiger Capture für Elemente, die kein server-seitiges Äquivalent haben, so verdrahtet, dass das resultierende Event trotzdem denselben Same-Origin-REST-Pfad und denselben server-seitigen Fan-out wie ein echter Formular-Lead durchläuft. Du taggst das Element, Beaconry erledigt den Rest.
Die fünf Slots, und was jeder davon tatsächlich feuert
Es gibt fünf CSS-Klassen. Jede mappt auf einen kanonischen GA4-Event-Namen, und der Forwarder mappt diesen GA4-Namen dann auf das eigene Event-Vokabular jedes Kanals. Der Sinn, standardisierte Werbe-Events zu nutzen (statt eines generischen "click"-Events), ist, dass Meta, TikTok, Pinterest und der Rest ihr Optimierungs-Signal behalten: ein begin_checkout sagt Meta, auf Checkout-Intent zu optimieren, ein generisches Custom-Event sagt ihm nichts.
Hier ist das verifizierte Mapping, direkt aus setupClickTracking() in der mitgelieferten Engine und EVENT_MAP_GA4_TO_META im Forwarder. (Eine Sache zum Aufpassen: der Checkout-Slot feuert GA4 begin_checkout, nicht initiate_checkout. begin_checkout ist GA4s kanonische Schreibweise; der Forwarder ist das, was es in Metas InitiateCheckout übersetzt. Wer beide verwechselt, sendet ein Event, das GA4 still verwirft.)
| CSS-Klasse | GA4-Event | Meta-CAPI-Event | Typischer Einsatz |
|---|---|---|---|
.beaconry-checkout | begin_checkout | InitiateCheckout | Kaufen / Abonnieren / In-den-Warenkorb-Übergabe an einen externen Checkout |
.beaconry-lead | generate_lead | Lead | Angebotsanfrage, "Mit Sales sprechen", gegateter Download |
.beaconry-signup | sign_up | CompleteRegistration | Start der Gratis-Testversion, Account-Erstellung, Warteliste-Beitritt |
.beaconry-contact | contact | contact (Custom-Event) | Telefon / E-Mail / WhatsApp / "Termin buchen"-CTA |
.beaconry-cta | select_content | ViewContent | Generischer High-Intent-Button, den du trotzdem messen willst |
Zwei davon lösen sich auf eine Weise auf, die zu kennen sich lohnt. .beaconry-contact hat kein Meta-Standard-Event, also reicht der Forwarder den GA4-Namen unverändert durch, und Meta verzeichnet ein Custom-Event, das wörtlich contact heißt. .beaconry-cta mappt auf Metas ViewContent, was ein echtes Standard-Event ist, also trägt es Optimierungs-Gewicht, statt in einem Custom-Event-Bucket zu landen. Beides ist Absicht: ein Custom-Event ist immer noch trackbar, ein Standard-Event ist vorzuziehen, wenn eines passt. Derselbe GA4-Name fächert über deren eigene Maps zu TikTok, LinkedIn, Pinterest, Snapchat, Reddit, X, Google Ads und Microsoft Ads aus, du setzt den Slot also einmal und jeder konfigurierte Kanal bekommt sein natives Äquivalent.
Wie der Capture unter der Haube funktioniert
Das ganze Feature ist ein einziger delegierter Klick-Listener auf document, eingerichtet innerhalb der mitgelieferten nl-data.js-Engine. Es gibt kein Per-Button-Binding, es funktioniert also weiter für Elemente, die nach dem Page-Load hinzugefügt werden (eine von einem Block gerenderte Preistabelle, ein später injiziertes Modal). Der Listener läuft vom Klick-Ziel mit closest() nach oben, um einen getaggten Vorfahren zu finden, liest die gematchte Klasse, baut die Payload und schickt sie ab.
Die Auslieferung nutzt navigator.sendBeacon(). Dieses Detail zählt mehr, als es aussieht. Ein normaler fetch(), der auf einem Klick gefeuert wird, der den Browser auch wegnavigiert (ein externer Kaufen-Link), wird mitten im Flug abgebrochen, wenn die Seite entlädt, und das Event geht verloren. sendBeacon() ist genau dafür gebaut: der Browser garantiert, dass der Request in die Queue kommt und gesendet wird, selbst während die Seite abgebaut wird. Ein Kaufen-Button kann also gleichzeitig zum externen Checkout navigieren und seine Conversion zuverlässig feuern.
Ab da ist das Event ganz gewöhnlich. Es POSTet an /wp-json/beaconry/v1/event auf deiner eigenen Domain (Same-Origin, Adblocker können es also nicht verwerfen, ohne WordPress zu brechen), der REST-Endpoint validiert Consent und normalisiert den Namen, und BCNR_Forwarder::dispatch() fächert es server-seitig aus. Es läuft kein kanalspezifischer Browser-Code. Das ist der ganze Grund, warum eine generische CSS-Klasse zehn Werbeplattformen auf einmal füttern kann: der Slot muss nur einen kanonischen GA4-Namen produzieren, und die bestehende server-seitige Maschinerie übernimmt jede Vendor-Übersetzung.
Ein in die Engine eingebauter Schutz: wenn Click-Tracking aktiv ist, überspringen die Auto-Events für ausgehende Links und Kontakt-Links jedes Element, das bereits eine .beaconry-*-Klasse trägt, sodass ein getaggter Kaufen-Button nicht auch noch ein generisches click- oder contact-Auto-Event feuert. Du bekommst eine saubere Conversion, kein verdoppeltes Signal. (Wenn Click-Tracking ausgeschaltet ist, werden diese Klassen als rein dekorativ behandelt und die Auto-Events feuern normal, sodass eine vergessene Klasse in einem Theme-Template nie still ein Signal verschluckt.)
Per-Button-Overrides mit data-Attributen
Die Klasse wählt den Event-Typ. Data-Attribute füllen die Werte für genau diesen Button. Alles ist optional: eine nackte Klasse feuert eine Null-Wert-Conversion mit dem eigenen Text des Buttons als Label, was für einen Kontakt-CTA in Ordnung ist. Ein Kaufen-Button will meist einen Preis und eine Produkt-Identität, damit der Wert im Reporting landet und das Katalog-Matching für Dynamic Product Ads funktioniert.
| Attribut | Geht an | Hinweise |
|---|---|---|
data-bcnr-value | Event-value + items[0].price | Numerisch. Fällt zurück auf den Per-Slot-Default aus dem Tracking-Tab, dann 0. |
data-bcnr-currency | Event-currency | Drei-Buchstaben-ISO, automatisch in Großbuchstaben. Default ist deine konfigurierte Währung, dann EUR. |
data-bcnr-content-id | content_ids[] + items[0].item_id | Deine SKU oder dein Tier-Slug. Mit Angabe baut es ein Single-Item-items[]-Array, damit GA4 das Event für Umsatz-Reports akzeptiert. |
data-bcnr-content-name | content_name + items[0].item_name | Menschenlesbarer Produktname. |
data-bcnr-label | Event-label | Überschreibt den automatisch erfassten Button-Text. Praktisch, wenn der sichtbare Text ein Icon oder zu generisch ist. |
Ein echter Kaufen-Button, der an einen externen Polar-Checkout übergibt:
<a class="beaconry-checkout"
href="https://buy.polar.sh/polar_cl_WVaBy3MStSJXOSCilMYu4RhA5DBFcGicJbgHo1IkT3A"
data-bcnr-value="149"
data-bcnr-currency="USD"
data-bcnr-content-id="studio-tier"
data-bcnr-content-name="Beaconry Studio">
Buy Studio
</a>Beim Klick feuert das GA4 begin_checkout mit Wert 149 USD und einem Ein-Item-items[]-Array, das der Forwarder in Meta InitiateCheckout, TikTok InitiateCheckout, Pinterest checkout und so weiter verwandelt, jeweils mit der angehängten Content-ID fürs Katalog-Matching. Der Besucher landet im Polar-Checkout; die Conversion wurde mit sendBeacon() in die Queue gelegt, bevor die Navigation abgeschlossen war.
Ein Kontakt-CTA, der nichts außer der Klasse braucht:
<a class="beaconry-contact" href="tel:+1-555-0142">
Call us
</a>Das feuert GA4 contact mit Wert 0 und dem Label "Call us", auf Meta als Custom-contact-Event verzeichnet und an das Lead-artige Äquivalent jedes anderen Kanals geroutet. Kein Wert, keine Content-ID, weil ein Telefonanruf keine hat. Wenn du später entscheidest, dass Telefon-Leads einen festen Schätzwert wert sind, füge data-bcnr-value="50" hinzu und nichts anderes ändert sich.
Wann du Click-Tracking nimmst, und wann nicht
Click-Tracking ist das richtige Werkzeug, wenn die Conversion keinen server-seitigen Fußabdruck auf deiner Site hat. Nimm es für externe Checkout-Übergaben (Polar, Stripe Payment Links, Gumroad), für Off-Site-Buchungs- und Terminlinks, für tel- / mailto- / WhatsApp-CTAs und für Affiliate- oder Partner-Links, die du trotzdem attribuieren willst. In all diesen Fällen ist der Klick der einzige Moment, in dem du die Intent beobachten kannst.
Es ist das falsche Werkzeug, wenn bereits ein präziser server-seitiger Hook existiert, und es dort einzusetzen kostet dich aktiv Genauigkeit:
- Echte Formular-Submits gehören zu den Formular-Integrationen, nicht zum Click-Tracking. Die Formular-Hooks feuern auf dem tatsächlichen Submit (nach der Validierung, nachdem der Lead gespeichert ist) und können gehashte PII (E-Mail, Telefon) für die Match-Rate anhängen. Ein Klick auf den Submit-Button feuert zu früh: er kann nicht sehen, ob die Validierung bestanden hat, und er hat keine Felddaten. Tagge stattdessen das Formular im Forms-Tab.
- WooCommerce-, EDD- und SureCart-Käufe gehören zum Commerce-Funnel. Die feuern aus Order-Hooks mit dem echten Gesamtwert, den echten Line Items und einer stabilen Per-Order-Event-ID, sodass ein Refresh der Danke-Seite nie doppelt zählt. Ein Klick auf "Bestellung aufgeben" hat nichts davon und würde fehlfeuern, egal ob die Zahlung tatsächlich durchging oder nicht.
- Ein On-Site-Multi-Step-Checkout ist Aufgabe des Commerce-Funnels, gemessen als
begin_checkoutohne folgendespurchase. Übertünche das nicht mit einem.beaconry-checkout-Klick auf den "Weiter"-Button.
Die Faustregel: wenn die Conversion einen Server-Hook produziert, nimm die Integration, die darauf lauscht, weil sie mehr sieht (Gesamtwerte, Items, PII) und zum richtigen Moment feuert. Wenn die Conversion eine Navigation oder eine reine Browser-Aktion ohne Hook ist, ist genau das, wofür Click-Tracking da ist.
Einschalten
Click-Tracking ist standardmäßig aus. Schalte es ein unter WordPress-Admin, Beaconry, Tracking, Click-Tracking, wo du auch die Per-Slot-Default-Werte setzen kannst, die ein Button nutzt, wenn er kein eigenes data-bcnr-value hat. Ab dann ist jedes Element auf der Site, das eine der fünf Klassen trägt, live.
Für Staging-Sites, die sich eine Produktiv-Datenbank teilen, gibt es einen harten Kill-Switch: define( 'BCNR_CLICK_TRACKING_ENABLED', false ); in wp-config.php überschreibt den Datenbank-Toggle, sodass eine Staging-Kopie nie Click-Conversions feuert, obwohl sie die "An"-Einstellung von der geklonten Datenbank geerbt hat. (Dieselbe Konstante auf true gesetzt erzwingt die Aktivierung, aber der Datenbank-Toggle ist der normale Weg.)
Wenn du für einen Kanal auch Hybrid-Modus fährst (das Browser-Pixel neben dem server-seitigen Dispatch), spiegelt Click-Tracking das Event automatisch mit derselben Event-ID an dieses Pixel, sodass der Vendor die Browser- und Server-Kopie zu einer dedupliziert. Das ist derselbe Dedup-Mechanismus, den die Commerce- und Formular-Pfade nutzen, behandelt im unten verlinkten Hybrid-Modus-Beitrag.
Mitnahme
Click-Tracking ist die Notluke für Conversions, die nie einen Server-Hook berühren. Fünf CSS-Klassen (checkout, lead, signup, contact, cta) mappen jeweils auf ein Standard-Werbe-Event, sodass eine einzige Klasse auf einem Kaufen-Button oder einem Kontakt-CTA zu jedem konfigurierten Kanal im Vokabular dieses Kanals ausfächert. Data-Attribute fügen Wert und Produkt-Identität pro Button hinzu. sendBeacon() sorgt dafür, dass es die Wegnavigation überlebt. Und der Same-Origin-REST-Pfad plus der gemeinsame server-seitige Forwarder bedeuten, dass das Ganze adblock-resistent und vendor-agnostisch ist, ohne eine Zeile Integrations-Code. Greif dazu, wenn es keinen Hook zum Lauschen gibt, und überlass die präzisen Pfade (Formulare, Commerce) den Integrationen, die ihnen gehören.