The RocketLead form widget emits browser events and POSTs every submission as JSON to your webhook. Use either side for pixel tracking (Meta, TikTok, Google Ads), GTM integrations, or downstream automation.
Available events
Event | Description | Key fields | dataLayer |
| Form loaded | formId, studioId | ✓ |
| Step navigation | formId, step | ✓ |
| Field value changed (every keystroke) | formId, fieldId, fieldName? | — |
| Field lost focus | formId, fieldId, fieldName? | — |
| Submission started | formId | ✓ |
| Submission succeeded | formId, submissionId, formData, bookingSlot | ✓ |
| Submission failed | formId, errorCode | ✓ |
| Booking slot selected | formId, fieldId, fieldName?, slotKey | ✓ |
| Captcha passed | formId, provider | ✓ |
| Fields prefilled on mount | formId, studioId, prefilledFieldIds | ✓ |
Note: rl:form:field:change and rl:form:field:blur are deliberately not pushed to the GTM dataLayer — they fire on every keystroke / focus-leave and would flood the container with per-field noise. Both still fire as DOM CustomEvents, so you can subscribe via document.addEventListener(...) when you need them.
Stable field names
Each form field can have a user-defined Name (in the editor → field settings). When set, it appears in two places:
As the HTML
name=""attribute on the rendered input — for stable DOM selectors likeinput[name="email"]across every form on your domain.As the
fieldNameproperty on field- and booking-events — usable directly in GTM triggers without walking the DOM.
Fields without a name set fall back to the internal field id. Consumers should treat fieldName as optional with a fallback to fieldId.
Listening to events
document.addEventListener('rl:form:submit:success', (e) => { const { formId, submissionId, formData, bookingSlot } = e.detail; // formData contains submitted values keyed by the field name // e.g. { email: '[email protected]', firstName: 'Max', phone: '+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, // for deduplication }); fbq('init', 'YOUR_PIXEL_ID', { em: formData.email, ph: formData.phone, fn: formData.firstName, }); });
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.phone, }); });
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.phone, } }); });
Google Tag Manager (GTM)
Prerequisite: window.dataLayer must exist. The widget never creates the dataLayer itself. If the GTM snippet is on the page, window.dataLayer = window.dataLayer || [] already exists and pushes work automatically. Without GTM or with a renamed dataLayer, pushes silently no-op.
If you need pushes but don't use GTM, initialise the dataLayer yourself before the widget loads:
<script>window.dataLayer = window.dataLayer || [];</script> <script src="https://cdn.rocketlead.io/static/forms/widget.js" defer></script>
GTM setup
Create a Custom Event trigger for
rl:form:submit:successCreate Data Layer Variables for
formData.email,formData.phoneetc.Use these variables in your Meta / TikTok / Google Ads tags
Webhook payload
When you configure a Webhook URL in the form settings, RocketLead POSTs a JSON payload to that URL on every submission. Retry policy: up to 4 attempts with exponential backoff (30s → 60s → 120s → 300s).
Payload shape
{ "event": "form.submission", "formId": "6bb76cc2-caee-4154-ad60-f4da93bb24f7", "formName": "Trial Lesson 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": "Studio", "type": "location", "name": "studio", "resolved": { "label": "Berlin Mitte" } }, "field-apt-xyz": { "label": "Course interest", "type": "appointment-type", "name": "courseInterest", "resolved": { "label": "Beginner course" } }, "field-email": { "label": "Email", "type": "email", "name": "email" } }, "resolvedData": { "studio": "Berlin Mitte", "courseInterest": "Beginner course", "email": "[email protected]" } }
Fields
Field | Description |
| Raw values keyed by field id. UUIDs (e.g. studio id, appointment-type id) are preserved — for audit / forensics. |
| UUID of the created Lead-Pool entry. |
| UUID of the created booking. |
| Per-field metadata (label, type, name, resolved labels for UUID fields). Contains an entry for every field in the published config — including unanswered and conditionally hidden fields. |
| Flat projection keyed by the stable field name (fallback: field id), with human-facing values pre-substituted. Convenient for Make.com / n8n / Zapier. |
Example handler
app.post('/webhook', (req, res) => { const { resolvedData, fieldContext } = req.body; // Fast path: read pre-resolved values directly by field name console.log(`Email: ${resolvedData.email}`); console.log(`Course interest: ${resolvedData.courseInterest}`); console.log(`Studio: ${resolvedData.studio}`); res.status(200).end(); });
Note: data is frozen at submission time — UUIDs never change across retries. fieldContext and resolvedData are rebuilt on every delivery attempt, so a later delivery reflects admin renames of appointment types / calendars / resources.
Related articles
For more on prefilling fields from URL params, the embed code, persistence, or editor defaults — including the precedence order in which these sources override each other:
Debug mode
To see all events in real time during development, place a debug panel next to the form:
<div data-rocketlead-form data-form-id="your-form-id"></div> <div data-debug-form-id="your-form-id"></div>
The debug panel displays events with timestamps and full payloads as they fire.
