Zum Hauptinhalt springen

Formular-Widget: Events, Pixel-Tracking & Webhooks

So nutzt du Formular-Events für Meta Pixel, TikTok, Google Ads, GTM und den Webhook-Empfang

M
Verfasst von Maxim Tan

Das RocketLead-Formular-Widget löst Browser-Events aus und schickt jede Absendung als JSON an deinen Webhook. Du kannst beides für Pixel-Tracking (Meta, TikTok, Google Ads), GTM-Integrationen oder serverseitige Verarbeitung nutzen.

Verfügbare Events

Event

Beschreibung

Wichtige Felder

dataLayer

rl:form:view

Formular geladen

formId, studioId

rl:form:step

Schritt-Navigation

formId, step

rl:form:field:change

Feld-Wert geändert (jeder Tastendruck)

formId, fieldId, fieldName?

rl:form:field:blur

Feld verlassen

formId, fieldId, fieldName?

rl:form:submit:start

Absendung gestartet

formId

rl:form:submit:success

Absendung erfolgreich

formId, submissionId, formData, bookingSlot

rl:form:submit:error

Absendung fehlgeschlagen

formId, errorCode

rl:form:booking:slot

Buchungs-Slot ausgewählt

formId, fieldId, fieldName?, slotKey

rl:form:captcha:success

Captcha bestanden

formId, provider

rl:form:prefill

Felder beim Mount vorbefüllt

formId, studioId, prefilledFieldIds

Hinweis: rl:form:field:change und rl:form:field:blur werden bewusst nicht in den GTM-dataLayer gepusht — sie feuern bei jedem Tastendruck bzw. Fokus-Verlust und würden den Container mit Per-Field-Rauschen überfluten. Beide stehen weiterhin als DOM-CustomEvents zur Verfügung, falls du sie per document.addEventListener(...) abonnieren möchtest.

Stabile Feldnamen

Jedes Formularfeld kann einen benutzerdefinierten Name haben (im Editor → Feldeinstellungen). Wenn gesetzt, taucht er an zwei Stellen auf:

  • Als HTML-Attribut name="" auf dem gerenderten Input — für stabile DOM-Selektoren wie input[name="email"] über alle Formulare hinweg.

  • Als fieldName-Eigenschaft in den Field- und Booking-Events — direkt in GTM-Triggern nutzbar, ohne den DOM zu durchlaufen.

Felder ohne gesetzten Namen fallen auf die interne Feld-ID zurück. Konsumenten sollten fieldName als optional behandeln und auf fieldId zurückfallen.

Events abonnieren

document.addEventListener('rl:form:submit:success', (e) => {
  const { formId, submissionId, formData, bookingSlot } = e.detail;
  // formData enthält die abgesendeten Werte, gekeyed nach dem Feld-Name
  // z.B. { email: '[email protected]', vorname: 'Max', telefon: '+491701234567' }
});

Meta Pixel

document.addEventListener('rl:form:submit:success', (e) => {
  const { formId, submissionId, formData } = e.detail;
  fbq('track', 'Lead', {
    content_name: formId,
    external_id: submissionId, // für Deduplizierung
  });
  fbq('init', 'YOUR_PIXEL_ID', {
    em: formData.email,
    ph: formData.telefon,
    fn: formData.vorname,
  });
});

TikTok Pixel

document.addEventListener('rl:form:submit:success', (e) => {
  const { formId, formData } = e.detail;
  ttq.track('SubmitForm', {
    content_id: formId,
    email: formData.email,
    phone_number: formData.telefon,
  });
});

Google Ads Enhanced Conversions

document.addEventListener('rl:form:submit:success', (e) => {
  const { submissionId, formData } = e.detail;
  gtag('event', 'conversion', {
    send_to: 'AW-XXXXX/XXXXX',
    transaction_id: submissionId,
    user_data: {
      email: formData.email,
      phone_number: formData.telefon,
    }
  });
});

Google Tag Manager (GTM)

Voraussetzung: window.dataLayer muss existieren. Das Widget legt den dataLayer nicht selbst an. Wenn das GTM-Snippet auf der Seite installiert ist, ist window.dataLayer = window.dataLayer || [] bereits vorhanden und Pushes funktionieren automatisch. Ohne GTM oder mit umbenanntem dataLayer machen die Pushes still nichts.

Wenn du Pushes brauchst, aber kein GTM einsetzt, initialisiere den dataLayer selbst, bevor das Widget lädt:

<script>window.dataLayer = window.dataLayer || [];</script> <script src="https://cdn.rocketlead.io/static/forms/widget.js" defer></script>

GTM-Einrichtung

  1. Erstelle einen Custom Event-Trigger für rl:form:submit:success

  2. Erstelle Data Layer Variables für formData.email, formData.telefon usw.

  3. Verwende diese Variablen in deinen Meta-/TikTok-/Google-Ads-Tags

Webhook-Payload

Wenn du in den Form-Einstellungen eine Webhook-URL hinterlegst, schickt RocketLead bei jeder Absendung eine JSON-Payload an diese URL. Retry-Strategie: bis zu 4 Versuche mit exponentiellem Backoff (30s → 60s → 120s → 300s).

Payload-Struktur

{
  "event": "form.submission",
  "formId": "6bb76cc2-caee-4154-ad60-f4da93bb24f7",
  "formName": "Probetraining Berlin",
  "submittedAt": "2026-04-22T12:00:00Z",
  "data": {
    "field-loc-abc": "3a1b2c4d-5e6f-4a8b-9c0d-1e2f3a4b5c6d",
    "field-apt-xyz": "7d9e8f2c-4b1a-4c3d-8e5f-6a7b8c9d0e1f",
    "field-email": "[email protected]"
  },
  "tableEntryId": "17d2cdca-ddb4-445d-9713-81c1a1bb90e2",
  "calendarBookingId": null,
  "fieldContext": {
    "field-loc-abc": {
      "label": "Standort",
      "type": "location",
      "name": "standort",
      "resolved": { "label": "Berlin Mitte" }
    },
    "field-apt-xyz": {
      "label": "Kursinteresse",
      "type": "appointment-type",
      "name": "kursinteresse",
      "resolved": { "label": "Anfängerkurs" }
    },
    "field-email": {
      "label": "E-Mail",
      "type": "email",
      "name": "email"
    }
  },
  "resolvedData": {
    "standort": "Berlin Mitte",
    "kursinteresse": "Anfängerkurs",
    "email": "[email protected]"
  }
}

Felder

Feld

Beschreibung

data

Roh-Werte gekeyed nach Feld-ID. UUIDs (z.B. Studio-ID, Termintyp-ID) bleiben unverändert — für Audit/Forensik.

tableEntryId

UUID des erzeugten Lead-Pool-Eintrags. null bei Webhook-only-Formularen.

calendarBookingId

UUID der erzeugten Buchung. null wenn das Formular keinen Buchungskalender hat oder kein Slot gewählt wurde.

fieldContext

Per-Field-Metadaten (Label, Typ, Name, aufgelöste Labels für UUID-Felder). Enthält einen Eintrag für jedes Feld der veröffentlichten Konfiguration — inklusive nicht ausgefüllter und versteckter Felder.

resolvedData

Flache Projektion gekeyed nach dem stabilen Feldnamen (Fallback: Feld-ID), mit menschenlesbaren Werten direkt eingesetzt. Praktisch für Make.com / n8n / Zapier.

Beispiel-Handler

app.post('/webhook', (req, res) => {
  const { resolvedData, fieldContext } = req.body;  // Schneller Pfad: aufgelöste Werte direkt nach Feldnamen lesen
  console.log(`E-Mail: ${resolvedData.email}`);
  console.log(`Kursinteresse: ${resolvedData.kursinteresse}`);
  console.log(`Standort: ${resolvedData.standort}`);  res.status(200).end();
});

Wichtig: data ist ab dem Zeitpunkt der Absendung eingefroren — UUIDs ändern sich auch bei Retries nicht. fieldContext und resolvedData werden bei jedem Zustellversuch neu aufgebaut, sodass spätere Zustellungen Admin-Änderungen an Termintyp-/Kalender-/Ressourcen-Namen widerspiegeln.

Verwandte Artikel

Mehr zur Vorbefüllung von Feldern aus URL-Parametern, Embed-Code, Persistierung oder Editor-Defaults — inklusive der Reihenfolge, in der diese Quellen sich überschreiben:

Debug-Modus

Um alle Events während der Entwicklung in Echtzeit zu sehen, setze ein Debug-Panel neben das Formular:

<div data-rocketlead-form data-form-id="deine-form-id"></div>
<div data-debug-form-id="deine-form-id"></div>

Das Debug-Panel zeigt Events mit Zeitstempeln und vollständigen Payloads, sobald sie ausgelöst werden.

Hat dies deine Frage beantwortet?