Conditional logic

Use conditional logic to show or hide fields and layout blocks, route respondents between pages, or choose an ending. Conditions compare a field’s stored answer with a value.

Condition structure

A condition has a field name, an operator, and a value:

{ "field": "plan", "operator": "equals", "value": "Pro" }

For several conditions, use an array that alternates condition objects with "AND" or "OR". Nest an array to group conditions.

Conditions are evaluated from left to right, with no operator precedence. For example, A OR B AND C means (A OR B) AND C. Use [A, "OR", [B, "AND", C]] to express A OR (B AND C). Evaluation short-circuits. An empty condition array evaluates to false, so visible_if: [] hides an element.

Operators

OperatorBehaviour
equalsStrict equality; "7" does not equal 7.
not_equalsThe opposite of equals.
greater_thanCompares the stored value with >; strings and numbers are compared loosely.
less_thanCompares the stored value with <.
inChecks whether the field value matches an item in value, which must be an array. A non-array value returns false.
not_inChecks that the field value does not match an item in value, which must be an array. A non-array value returns true.
containsFor an array answer, checks for an exact element. Otherwise, checks for an exact match or substring.

There are no >=, <=, or is_empty operators.

For a matrix field, use "<name>.<rowId>" to test one row. Use "<name>" to test all rows: positive operators match if any row matches; not_equals and not_in match if no row matches. The condition value can be a column ID or label.

Where to use conditions

  • Set visible_if or hide_if on fields and layout blocks. An element is visible when visible_if is true or absent, and hide_if is false. Hidden fields skip validation, including required.
  • Set page.next to route to a page, an ending, or the next page. A go_to target can be a page ID, "end", or "next". The first matching branch wins, then default, then "next".
  • Set end_logic to choose an ending. The first matching branch wins, then default, then the first end page.

The only logic actions are show, hide, jump to a page, and choose an ending. Logic cannot reference CAPTCHA. CAPTCHA is a form setting. There are no set-value or calculate actions. Choices from pages skipped by the respondent’s path are dropped before the submission is stored.

Conditional endings

end_logic has a conditions array of branches with if and go_to, plus a top-level default ending target:

{ "mode": "page", "pages": [ { "type": "form", "id": "p1", "ui": [ { "type": "single_select", "name": "plan", "label": "Which plan do you use?", "options": ["Free", "Pro"], "required": true } ] } ], "end": [ { "id": "e0", "type": "end", "ui": [] }, { "id": "e1", "type": "end", "ui": [] } ], "end_logic": { "conditions": [ { "if": [ { "field": "plan", "operator": "equals", "value": "Pro" } ], "go_to": "e1" } ], "default": "e0" } }

Conditional endings and per-ending redirects run in page and tally modes, and when mode is unset. The server chooses the ending at submission after recomputing calculations. Malformed ending branches are skipped. Publishing rejects invalid end logic with INVALID_END_LOGIC when there are no endings, a target is missing, a redirect URL is invalid, or an ending is unreachable.

Examples

This config shows a follow-up field when the respondent selects the built-in Other choice as their contact preference. Built-in Other answers are stored as "Other: <text>", so the condition checks for the "Other:" substring:

{ "mode": "page", "pages": [ { "type": "form", "id": "p1", "ui": [ { "type": "multiple_choice", "name": "contact_preference", "label": "How should we contact you?", "options": ["Email", "Phone"], "has_other": true, "required": true }, { "type": "short_text_input", "name": "contact_details", "label": "What should we know about your preference?", "visible_if": [ { "field": "contact_preference", "operator": "contains", "value": "Other:" } ] } ] } ], "end": [ { "id": "e0", "type": "end", "ui": [] } ] }

This config routes respondents to p2 when they select Pro and have more than 10 seats. Otherwise, they go to the next page:

{ "mode": "page", "pages": [ { "type": "form", "id": "p1", "ui": [ { "type": "single_select", "name": "plan", "label": "Which plan do you use?", "options": ["Free", "Pro"], "required": true }, { "type": "number_input", "name": "seats", "label": "How many seats do you need?", "required": true } ], "next": { "conditions": [ { "if": [ { "field": "plan", "operator": "equals", "value": "Pro" }, "AND", { "field": "seats", "operator": "greater_than", "value": 10 } ], "go_to": "p2" } ], "default": "next" } }, { "type": "form", "id": "p2", "ui": [ { "type": "email_input", "name": "work_email", "label": "What is your work email?", "required": true } ] } ], "end": [ { "id": "e0", "type": "end", "ui": [] } ] }