ootb-lp-tracking
v1.0.0
Published
OOTB Tracking-Standard für Hotel-Landingpages: dataLayer-Events, CTA-Zuordnung, Lead-Versand an GuestFlow
Readme
ootb-lp-tracking
OOTB Tracking-Standard für Hotel-Landingpages als ein Paket statt 22 Kopien. Enthält nur, was auf allen LPs identisch sein muss:
dataLayer-Events, CTA-Zuordnung, Lead-Herkunftsfelder, Telefon- und Datumsregeln, Absenden mit Retry, Selbstprüfung.
Layout, Texte und Felder bleiben in der LP. Beschreibung des Standards: wissen/tracking-standard.md.
Einbinden
Statische LP – direkt vor dem eigenen Formular-Skript, ohne async/defer:
<script src="https://cdn.jsdelivr.net/npm/ootb-lp-tracking@1/dist/lp-tracking.min.js"></script>
<script>window.OOTBTracking||document.write('<script src="https://unpkg.com/ootb-lp-tracking@1/dist/lp-tracking.min.js"><\/script>')</script>@1 = immer die neueste 1.x. Bugfixes kommen ohne Änderung an den LP-Repos an. Bei Skripten mit defer (z. B. eigener Build):
beide Tags ebenfalls mit defer vor dem eigenen Skript, die document.write-Zeile entfällt.
Next.js / Bundler: npm i ootb-lp-tracking@^1, dann import OOTBTracking from "ootb-lp-tracking" und OOTBTracking.init(...) in einem
useEffect des Formular-Components.
Verwenden
var gf = OOTBTracking.init({ variant: FORM_VARIANT }); // "A" | "B" | "" (ohne A/B-Test)init macht automatisch: Listener für den zuletzt geklickten data-cta, form_variant (1×), form_start bei der ersten
Berührung eines Formulars [data-gf-form] oder #bookingForm (1× pro Seitenaufruf), data-gf-form="haupt" am #bookingForm,
Selbstprüfung in der Konsole. Doppelt geladenes Skript oder mehrfaches init ist harmlos.
| Funktion | Zweck |
|---|---|
| gf.stepComplete(step) | form_step_complete (Variante B, „Weiter“ erfolgreich) |
| gf.reportInvalid(scope, step?) | meldet alle markierten Felder (.error, aria-invalid="true", nicht angehakte Pflicht-Checkbox) als form_error, je Feld 1× |
| gf.reportErrors([feld…], step?) | dasselbe mit expliziter Liste (Elemente oder Namen) |
| gf.fieldName(el) | einheitlicher Feldname (s. u.) |
| gf.isValidPhone(wert) | ab 6 Ziffern; Leerzeichen, - / ( ) . und führendes + oder 00 erlaubt; keine Vorwahl-Whitelist |
| gf.bindPhoneInput(el) | Eingabefilter passend dazu (ersetzt den alten Filter auf [0-9 ]), inputmode="tel" |
| gf.buildPhone(vorwahl, wert) | Format wie bisher (00 + Ziffern). +/00 eingetippt → so übernommen. Führende 0 fällt weg, außer bei 0039/00378 |
| gf.bindDateRange(anreise, abreise) | frühestens heute, Abreise ≥ Anreise + 1 (wird nachgezogen). flatpickr (nach dessen Init aufrufen) oder type="date"; Textfeld ohne Kalender wird type="date" |
| gf.checkDates(a, b) | null oder "ankunft"/"abreise" |
| gf.toIsoDate(wert) | JJJJ-MM-TT für den Payload |
| gf.bindQuickForm(block) | Schnellanfrage (s. u.) |
| gf.submitLead(url, payload) | sendet den Lead (s. u.), Promise {ok, status, data} – wird nie abgelehnt |
| gf.formElapsedMs() | ms seit der ersten Formular-Berührung, für form_elapsed_ms |
| gf.leadFields() | {lp_cta, lp_variant, lp_device, lp_page} |
| gf.check() | Abweichungen vom Standard als Liste (leer = ok) |
| gf.push(event, data) | gfPush des Standards; auch als window.gfPush |
submitLead
Hängt lp_cta, lp_variant, lp_device, lp_page und lp_submit_id ans Ende des Payloads; bestehende Felder bleiben unverändert.
| Fall | Events | Ergebnis |
|---|---|---|
| HTTP ok und success: true | form_lead_success mit cta und form_data {room, guests, lead_id, device, variant} | ok: true |
| HTTP-Fehler oder success != true | lead_api_error {status: HTTP-Code} | ok: false |
| Netzabbruch, Retry nach 3 s klappt | lead_api_error {status: network_recovered} + form_lead_success | ok: true, recovered: true |
| Netzabbruch, Retry scheitert | lead_api_error {status: network_retry_failed} | ok: false |
Bei ok: false lässt die LP alle Eingaben stehen, zeigt ihre Meldung sichtbar im Formular (kein alert) und aktiviert den Knopf wieder.
Zusätzliche form_data-Felder: submitLead(url, payload, { formData: { landing_page: … } }).
lp_submit_id ist bei beiden Versuchen gleich – GuestFlow kann damit künftig Doppel-Einsendungen erkennen.
Feldnamen in form_error
ankunft, abreise, erwachsene, kinder, kinder_alter, zimmer, nachricht, vorname, nachname, email, phonePrefix, phoneNumber, privacy, verpflegung, haustiere.
Vorrang hat data-gf-field="…" am Feld, sonst Ableitung aus name, dann id (checkin → ankunft, phone-general → phoneNumber,
child_age_1 → kinder_alter). Unbekannte Felder behalten ihren bereinigten Namen, sonst unbekannt – nie leer.
Schnellanfrage
Zweiter, kleiner Block nach data-section="vorteile". Es gibt weiterhin nur ein echtes Formular.
<div class="gf-quick" data-gf-form="schnell">
<input type="text" data-gf-quick="ankunft"> <input type="text" data-gf-quick="abreise">
<select data-gf-quick="erwachsene">…</select> <select data-gf-quick="kinder">…</select>
<button type="button" data-cta="sektion_vorteile" data-gf-quick-submit>Verfügbarkeit anfragen</button>
</div>gf.bindQuickForm(block) überträgt die Werte in die gleichnamigen Felder des #bookingForm (über fieldName), springt zu #anfrage
und setzt den Fokus aufs erste leere Pflichtfeld. GTM: form_seen misst [data-gf-form] (einmal pro Seite).
Entwickeln und veröffentlichen
npm install && npm run build && npm testVersion in package.json und VERSION in src/index.js erhöhen (Build bricht sonst ab). Push auf main mit Änderungen unter
packages/lp-tracking/ → Workflow lp-tracking testet und veröffentlicht auf npm, wenn die Version neu ist, und leert den jsDelivr-Cache für @1.
Einmalig nötig: npm-Konto, Automation-Token als Repo-Secret NPM_TOKEN.
Neue Major-Version (2.0.0) nur bei inkompatiblen Änderungen – die LPs bleiben dann auf @1, bis sie umgestellt werden.
