Form Prefill: Cascade & Precedence
RocketLead forms can have field values prefilled from four different sources. This document explains the precedence between them, what each source can and cannot do, and how to pin values that visitors must not be able to override.
The cascade
Section titled “The cascade”When the widget mounts, it walks four prefill sources in order. Each layer can fill empty slots; higher-priority layers blindly overwrite lower-priority ones. Final priority, from highest to lowest:
| # | Source | Wins over | Authored by |
|---|---|---|---|
| 1 | Embed prefill option | URL params, persistence, defaults | The page that hosts the embed (developer JS) |
| 2 | URL query params | Persistence, defaults | The visitor’s URL bar / inbound link |
| 3 | localStorage persistence | Defaults | The visitor (return-visit autofill) |
| 4 | Field defaultValue | (bottom) | The form editor (config) |
Mental model: most-explicit-context wins. Code beats URL bar beats local storage beats static config.
A field that no source provides a value for stays empty.
Source 1 — Embed prefill (highest priority)
Section titled “Source 1 — Embed prefill (highest priority)”Set when calling window.rocketlead.forms.create() from your page’s JavaScript:
<div id="rl-form"></div><script src="https://cdn.rocketlead.io/static/forms/widget.js" defer></script><script> window.rocketlead.forms.create({ target: '#rl-form', formId: 'shared-form-id', // keys are field IDs (grab them from the editor's developer panel) prefill: { '<location-field-id>': 'studio-uuid-for-this-page' }, hideFields: ['<location-field-id>'] });</script>Keys must be field IDs. Embed prefill and hideFields resolve only against fieldId. The fieldMappingKey (the field’s stable name) is not honored here — even though it is on the URL-params source. Unknown keys are dropped silently.
Grab the fieldId from the editor: open the field’s settings, expand the developer panel, copy the ID. Field IDs are stable across publishes; renaming the field’s label doesn’t change them.
Because embed prefill is the highest-priority source, this is how you pin a value that visitors cannot override — even with a crafted URL. See Hidden fields below.
Skipped in the editor’s preview. The console preview renders defaults but does not simulate the embed surface.
Source 2 — URL query params
Section titled “Source 2 — URL query params”The visitor’s URL automatically prefills matching fields. Two key conventions:
https://your-site.com/contact?fieldId=valuehttps://your-site.com/contact?yourMappingKey=valuefieldId wins on collision with another field’s mappingKey.
Multi-value (checkbox) fields: repeat the key.
?days=mon&days=wedBooking-calendar fields are special — a URL value is interpreted as an appointment-type id to preselect inside the calendar, not a slot. Slots are always picked interactively against live availability.
Privacy and captcha fields can never be prefilled from URL params (consent must be explicit, captcha tokens come from the third-party provider at submit time).
Source 3 — localStorage persistence
Section titled “Source 3 — localStorage persistence”If the form has persistence enabled in the editor, listed sharedFields are read from localStorage on mount and written on every change. This is the “return visitor autofill” mechanism — surveys, multi-step funnels, abandoned-and-returned flows.
The persistence bucket is keyed by formId, so two embeds of the same form on the same domain share their bucket.
Source 4 — Field defaultValue (lowest priority)
Section titled “Source 4 — Field defaultValue (lowest priority)”A static fallback authored in the form editor. Only fills slots no other source filled.
| Field type | defaultValue shape | Validation |
|---|---|---|
text / email / tel | string | respects maxLength; truncated silently at runtime, rejected at publish |
select / location | string | must match one of field.options[].value |
checkbox | string[] (non-empty) | every entry must match an option |
booking-calendar | — | not supported |
appointment-type | — | not supported (planned) |
captcha / privacy | — | not supported |
Defaults run in the editor’s preview, so the editor reflects what visitors will see.
Hidden fields
Section titled “Hidden fields”The embed-level hideFields option removes a field from the rendered form while keeping its value in the submission payload. Combined with prefill, this is the multi-instance pattern — one published form, N embeds, each pinning a different value.
window.rocketlead.forms.create({ target: '#rl-form', formId: 'lead-form', prefill: { '<location-field-id>': 'studio-uuid', '<utm-source-field-id>': 'google' }, hideFields: ['<location-field-id>', '<utm-source-field-id>']});Behaviour:
- The renderer skips hidden fields. They never appear in step bodies or in the review/summary step.
- Their values stay in
formValues, so studio routing (location), validation, and submission all still see them. - URL params targeting a hidden field are silently dropped. A crafted
?location=other-studiolink cannot override what the embedder pinned. The embedprefillitself is allowed because the embedder is the source of authority. - Validation is unchanged. A hidden required field without a matching
prefillwill fail at submit — the visitor sees a generic error with nothing to fix. The widget logsconsole.warnon mount when this is the case.
Validation & sanitisation
Section titled “Validation & sanitisation”Every prefill source applies the same defensive rules; mismatches are dropped silently rather than crashing the form.
- Sanitisation — text inputs (text/email/tel) and option keys are stripped of
<,>, and ASCII control characters (U+0000–U+001F and U+007F) before further processing. Values that become empty after stripping are dropped. - Option match —
select,location, andcheckboxvalues must match one of the field’s publishedoptions[].value. Stale or unknown values are dropped. - maxLength — text values exceeding the field’s
maxLengthare truncated silently at the widget; the publish API rejects them outright (the only chance to surface the error is at publish time). - Type shape — non-string passed to a string field, or non-array to a checkbox, is dropped.
Quick reference — what each field type accepts
Section titled “Quick reference — what each field type accepts”| Field type | Embed prefill | URL params | Persistence | defaultValue | Notes |
|---|---|---|---|---|---|
text / email / tel | ✓ | ✓ | ✓ | ✓ | sanitised, maxLength-capped |
select / location | ✓ | ✓ | ✓ | ✓ | must match options[] |
checkbox | ✓ | ✓ | ✓ | ✓ | array, must match options[] |
booking-calendar | — | ✓¹ | — | — | URL value preselects appointment type, not slot |
appointment-type | — | — | — | — | per-calendar default planned |
captcha | — | — | — | — | token issued by provider at submit |
privacy | — | — | — | — | GDPR — explicit consent only |
¹ URL ?bookingCalendarFieldId=appointmentTypeUuid is captured into initialAppointmentTypeIds and applied after the appointment-types fetch resolves.
Examples
Section titled “Examples”One form, many locations
Section titled “One form, many locations”A franchise with five WordPress sites embeds the same form on each site, pinning a different studio per page:
<div id="rl-form"></div><script> window.rocketlead.forms.create({ target: '#rl-form', formId: 'shared-lead-form', prefill: { '<location-field-id>': 'studio-1-uuid' }, hideFields: ['<location-field-id>'] });</script><!-- studio2.example.com/contact — same form, different studio --><script> window.rocketlead.forms.create({ target: '#rl-form', formId: 'shared-lead-form', prefill: { '<location-field-id>': 'studio-2-uuid' }, hideFields: ['<location-field-id>'] });</script>Submissions land on each studio’s correct calendar / lead-pool table automatically — the location field drives studio resolution under the hood, even when hidden.
Campaign tracking from URL
Section titled “Campaign tracking from URL”A tracking field (configured as a hidden text field at the form-config level when that’s available — for now, use the embed-level hideFields pattern below) carries the utm_source from inbound campaign links:
https://your-site.com/contact?utm_source=google&utm_campaign=spring2026Until config-level hidden ships, you can replicate the pattern at the embed level:
const params = new URLSearchParams(window.location.search);window.rocketlead.forms.create({ target: '#rl-form', formId: 'lead-form', prefill: { '<utm-source-field-id>': params.get('utm_source') ?? 'direct', '<utm-campaign-field-id>': params.get('utm_campaign') ?? '' }, hideFields: ['<utm-source-field-id>', '<utm-campaign-field-id>']});Default value with override
Section titled “Default value with override”The form’s email_subject field has a defaultValue of "Anfrage Probetraining" set in the editor. A campaign page links visitors with a custom subject:
https://your-site.com/landing?email_subject=Sommer-AktionResult: "Sommer-Aktion" (URL beats default). If the visitor returns later without the URL parameter, persistence (if enabled) shows their last-typed value, otherwise the editor default reappears.
Common pitfalls
Section titled “Common pitfalls”- “My default isn’t showing in the published form” — make sure no other source is filling the slot. URL params and persistence both override defaults. Test in an incognito window without query strings to confirm.
- “My embed prefill isn’t applying” — the key didn’t resolve. Embed
prefillandhideFieldsaccept onlyfieldId, notfieldMappingKey. Grab the ID from the field’s settings (developer panel). If you were keying off the mapping name, that’s why nothing applied. - “Validation says my form is incomplete but I can’t see why” — a hidden required field has no matching
prefill. Open devtools — the widget logs aconsole.warnat mount listing each affected field. - “My select/location prefill is ignored” — the value isn’t in the field’s
options[]. Check the editor’s option list against what your embed/URL is sending.
Related
Section titled “Related”- Embedding — the widget script and the SPA
create()API that takesprefill. - Field Types — what each type accepts as a prefill value (and what types can’t be prefilled).
- Events —
rl:form:prefillfires when prefill is applied at mount.