Nothing renames. In the survey editor these are still the Hidden Fields and Variables cards, and the
API payloads are unchanged. Embedded Data is the name for those two plus the auto-captured fields, now that
they share one type system and one read path. See Hidden Fields and
Variables if you already use them.
The Three Sources
Every Embedded Data field has exactly one source, and the source decides who is allowed to write it.
Ingested fields are the only ones anything outside the survey can write. Computed fields are set by logic while the respondent answers, and reserved fields are read-only auto-capture, so a URL param or an SDK call naming one of them is dropped and logged rather than stored.
Where Values Come From
Which capture channel is available depends on the survey type, and this is the part worth reading twice, because a URL param does nothing for an app survey andsetEmbeddedData() does nothing for a link survey.
Mobile SDKs render the survey inside a WebView that has no host page, so
location and document.referrer
describe nothing real there. The page and campaign fields are left absent on mobile responses rather
than filled with a meaningless value. The device fields are honest measurements of the device and are
captured. If you want the equivalent of a page name on mobile, pass it yourself:
setEmbeddedData({ screen: "checkout" }).plan is declared the same way, filled by ?plan=pro on a link survey and by setEmbeddedData({ plan: "pro" }) on an app survey, and reads back identically in recall, logic, filters and exports.
Declaring a Field
An ingested or computed field has to exist on the survey before anything can fill it. Add it in the survey editor: Hidden Fields for ingested, Variables for computed. Reserved fields are never declared, they are always available. A field’s name is the key you use everywhere: in a URL parameter, insetEmbeddedData(), in recall tokens, in logic operands and as the export column header.
Field names follow one rule everywhere, and reserved names are refused for new fields in any casing. The full rule and the refused list live on the Hidden Fields page.
A field also carries a type that decides how its value is read back and compared. In this release:
- Hidden fields are
string. Anything you pass is stored as text. - Variables are text or number, and the initial value you set in the editor is the default the field falls back to.
- Reserved fields are typed by Formbricks, and several of them are genuinely numeric:
viewportWidth < 768is a numeric comparison in logic, not a comparison of digit strings.
Typing hidden fields (
number, boolean, date), giving them a default, and locking a field so nothing
outside the survey can write it, are part of the Embedded Data manager and are not authorable yet. The
ingest rules below already honour all of them, so nothing changes for you when they arrive.What Happens to an Incoming Value
The same contract runs in the browser when the survey is displayed, and again on the server when the response is saved, so what the client accepts is never taken on trust.1
Allow-list
Only names the survey declares as ingested fields are stored. An unknown key, a computed field, a
reserved field or a locked field is dropped and logged, never stored, and never an error.
2
Case-insensitive matching
A field declared
customerRef is filled by ?customerref=x as well as ?customerRef=x. The value is
always stored under the declared spelling, so exports and recall see one key.3
Coercion to the declared type
Values are coerced rather than rejected.
"42" into a number field becomes 42; true, 1, yes
and on (and their negatives) become booleans; a date field accepts 2026-08-06 and full ISO 8601
datetimes, stores ISO 8601, and reads a datetime with no zone as UTC rather than as the respondent’s
local time. A value that cannot be coerced is stored verbatim and flagged, so a bad parameter never
blocks a response. Today every hidden field is a string, and every scalar has a lossless text form, so
this step only starts doing visible work once fields can be typed.4
Size limit
One value is capped at 16 KB of UTF-8. Anything longer is truncated on a character boundary and
flagged, not rejected.
5
Collision with a question
A question’s answer always wins its own key. A field whose name collides with a question id can never
hold a value, and the collision is reported.
A field nothing arrived for keeps its key absent rather than empty, and reads back as its default value
if it has one. That is what makes
#recall:plan/fallback:unknown# show the fallback instead of a blank.Precedence
When two sources offer the same field on the same response, the more explicit one wins:- a question’s answer, always, for its own key;
- an explicit
formbricks.track("action", { hiddenFields: { plan: "pro" } })value; - the ambient bag set with
setEmbeddedData(), or the URL parameter on a link survey; - the field’s default value;
- otherwise the field is unset.
url or country, that name resolves to the declared field everywhere, and the reserved field of the same name is not offered, listed or exported for that survey.
Reading the Values Back
Once a value is on a response it behaves like any other response data:- Recall it into question copy, ending cards and redirect URLs with
#recall:<name>/fallback:<text>#. - Use it as a logic operand to branch the survey.
- Filter and group responses by it.
- Export it as a stable, typed column in CSV and Excel.
country or durationSeconds are only known once the response reaches Formbricks, so they are available on the response but not offered to a running survey. The Reserved Fields page marks which is which.
Next Steps
Reserved Fields
The full catalog of auto-captured fields, their types, and what the Anonymize toggle suppresses.
setEmbeddedData
The JavaScript SDK reference: merge semantics, SPA route changes, GTM and the debug trace.
Mobile SDKs
setEmbeddedData on React Native, iOS, Android and Flutter, with each language’s value types.Hidden Fields & Variables
What changes for surveys you already run, and what does not.