Skip to main content
Arm content can contain placeholders written as {{name|fallback}}. Two things fill them, and they are kept apart on purpose.

Variables: filled from the user

A variable is substituted at decision time from the user’s stored identifiers and attributes: {{first_name|there}} renders Hi Alice for a user whose first_name is known and Hi there otherwise. The fallback after the | is required, because an empty substitution renders broken copy. variables lists the names content may reference. On the first call for an element it defaults to the identifier and attribute keys you sent on that call, so any of those is available at once. Later calls update the list in place; existing arms keep rendering correctly under any list because every placeholder has a fallback. Names match ^\w+$. Variables are how content is personalized without the identifiers ever reaching the model: an email address can appear in copy and still never be a feature.

Parameters: facts you fix

A parameter is a fact about the content that every variant must reproduce verbatim: a plan name, a price, a date, a count. Curious substitutes it into the placeholder exactly as declared and generates variants that keep it. Keys match ^\w+$; values are any JSON, but only non-null scalars are substituted, while structured values are visible to generation as context. All parameters are required-display by definition. A fact that variants may mention or omit is not a parameter; put it in instructions instead. Parameters are fixed for the experiment’s life. Any change supersedes the experiment, because the arms were generated against the declared facts. The history of a parameter is the chain of experiments.

The two namespaces never overlap

A name is either a variable or a parameter. A declaration that lists the same name in both is a 400.

Where substitution happens

In the content of every decision response, before it reaches you. The stored arm keeps its placeholders. See Serve a decision.