chatformdocs

Pass values into a form

Hand a form values from the page, link or app that opens it, save them with each response and use them to steer the form.

A hidden field is a value the form receives without asking for it. It is not a question. The page that opens the form supplies it: a plan name from a pricing page, a customer id from your app, a campaign from a link.

What a hidden field does:

It does not appear in the conversation. A question cannot quote it with {{ref}} recall, which only reads answers.

Declare the field

Only declared names are accepted by the hosted page and the embed. Anything else in the link is ignored.

In the builder, open Settings, then Hidden fields & variables, type a name and press Enter. Over the API or MCP, add it to the form document:

{ "hiddenFields": [{ "name": "plan" }, { "name": "customer_id" }] }

A name starts with a letter or underscore, then letters, digits, _, . or -, up to 61 characters. Names are case sensitive: plan and Plan are different fields.

Add the name as a query parameter to the form's link:

https://chatform.in/f/your-form-slug?plan=pro&customer_id=8271

Encode anything that is not plain text, as you would any URL (?note=two%20seats). A value is at most 500 characters. Repeat a name and the link is ambiguous, so it is ignored. A form takes at most 25 hidden fields.

Pass it through the embed

On the script tag, one data-hidden- attribute per field:

<script
  src="https://chatform.in/embed.js"
  data-form="your-form-slug"
  data-hidden-plan="pro"
  data-hidden-customer_id="8271"
  defer
></script>

HTML lowercases attribute names, so data-hidden-customerId arrives as customerid. Use lowercase field names if you pass them this way, or set them from script, which keeps your casing:

window.Chatform.prefill({ plan: "pro", customerId: "8271" });

Call prefill before the form opens. Values set after the conversation has started are not picked up, because a session reads its hidden fields once, when it begins.

An iframe takes the same query parameters as the link. In React, pass hidden:

<ChatformEmbed slug="your-form-slug" hidden={{ plan: "pro", customerId: "8271" }} />

Pass it from your server

A session opened through the API, and a response submitted through it, take a hiddenFields object:

curl -X POST https://api.chatform.in/v1/forms/$FORM_ID/sessions \
  -H "x-api-key: $CHATFORM_SECRET_KEY" \
  -H "content-type: application/json" \
  -d '{"hiddenFields": {"plan": "pro"}}'

The API does not check names against the form, so declare every field you send. The MCP tool submit_response takes the same object as hidden_fields.

Steer the form with it

A condition can read a hidden field wherever it reads an answer: a question's visibility, a branch, an ending rule, a rule that sets a variable. A condition may only name a declared field. Publishing fails otherwise.

{
  "left": { "kind": "hidden", "name": "plan" },
  "op": "eq",
  "value": "pro"
}

Test for the field being absent as well. A link that was copied without its parameters opens the form with nothing set.

Charge an amount that depends on a value

A payment question in Variable mode charges the value of a form variable. Rules set that variable, and a rule can test a hidden field. So a link can pick between amounts you wrote into the form.

Say the pricing page links to ?plan=pro or ?plan=team. Declare plan, add a number variable price, and add one rule per plan:

{
  "variables": [{ "name": "price", "type": "number", "initial": 0 }],
  "hiddenFields": [{ "name": "plan" }],
  "logic": [
    {
      "id": "r_price_pro",
      "action_kind": "set_variable",
      "when": {
        "op": "and",
        "groups": [],
        "conditions": [{ "left": { "kind": "hidden", "name": "plan" }, "op": "eq", "value": "pro" }]
      },
      "variable": "price",
      "expr": 99
    },
    {
      "id": "r_price_team",
      "action_kind": "set_variable",
      "when": {
        "op": "and",
        "groups": [],
        "conditions": [{ "left": { "kind": "hidden", "name": "plan" }, "op": "eq", "value": "team" }]
      },
      "variable": "price",
      "expr": 299
    }
  ]
}

Then set the payment question to Variable and choose price, with a minimum and maximum as a guard. The amount is worked out on the server, so the respondent sees and pays what your rules say. Rules run after each answer, so the payment question needs at least one question before it.

A link can choose between prices you have written down. It cannot carry a price of its own. A rule can test a hidden field but cannot copy its value into a variable, so a cart total such as ?total=4999 is saved with the response and never charged. That is deliberate: anyone can edit a link, and an amount taken from one would let a visitor set their own price. Charge a total your server computes by creating the payment on your own gateway and sending the respondent there, or give each product a rule as above.

Verified checkout is described in Verified payments.

On this page