Survey definition

Last updated
On this page

Conversational voice (Pip’s Text or voice mode) is not generally available and is marked Coming soon. Ordinary text-question dictation is a separate feature; see conversation availability.

The CLI accepts a complete survey definition file for prompt create and prompt update. Updates replace the editable definition rather than patching a few fields. Start with the valid first survey definition.

Top-level fields

All fields in this table are required. Unknown fields are rejected.

Field Type and meaning
schema_version 1.
name Internal name, 1–240 characters.
content Questions, presentation and language; described below.
rules { schema_version: 1, audience, triggers, frequency }, with an optional saved_audience; see Targeting.
sampling_percent Number from 0 to 100.
priority Integer from 0 to 2147483647. Higher wins.
enrollment_epoch Stable enrollment identifier. Keep it during ordinary edits to preserve the sample and each person's counts and waits.

Identifiers, including question and option IDs, start with a letter or digit and contain only letters, digits, ., _, : and -, up to 160 characters. They are not display labels. Keep them stable when wording changes; choose new IDs when the meaning changes.

Content

Required content fields are schema_version: 1, title (up to 240 characters), description (string up to 4000 or null), questions (1–64 entries), and thank_you (string up to 2000 or null).

Optional fields include invitation, asker, language, translations, collect_partial_responses and the explicit flow used for experiments. Explicit null is allowed for invitation and asker. Drafts may contain unfinished text; publication validates that questions, labels, images and translations are ready.

Text conversations with Pip are available in production and development through an optional conversation setting on an entry-only terminal text question, subject to workspace AI settings and allowance.

Supported choice, matrix and ranking questions can set answer_order; see Answer randomisation. Read Writing useful surveys for choosing wording, options and timing.

content.collect_partial_responses is an optional boolean, enabled when omitted or true. Set it to false to collect only the final response. SDK 0.4.0 or later saves validated answers when the visitor advances with Next; typing alone does not save them. See Partial responses for save boundaries and results.

Questions

Every question requires id, kind, prompt and required. Question IDs are unique within the survey. Question text is at most 2000 characters. The following fields are additional to those common fields.

Kind Required fields Optional fields and constraints
rating min, max, min_label, max_label Integer range within 0–10 with max greater than min. Endpoint labels are strings or null. Optional style and labels.
text max_length 1–10000 characters. Optional lines: 'single' or 'multiple'; single-line answers are limited to 200. Optional dictation: { language: 'prompt' | 'detect', filler_words: 'remove' | 'keep' } lets visitors answer by voice; see voice answers.
single_choice options 2–32 listed options, or up to 250 with display: 'dropdown'. Optional columns: 1 or 2. Dropdowns cannot use images.
multiple_choice options, min_selections, max_selections 2–32 options; selection limits must be positive and fit the options. Optional columns: 1 or 2.
matrix rows, min, max, min_label, max_label 2–5 unique rows, each { id, label }. Rating range 0–10. Optional style: 'numbers', 'stars' or 'hearts'.
ranking options, top 2–10 { id, label } options. top is the number to rank, from 1 to the number of options.
date entry, earliest, latest entry is 'picker' or 'parts'. Each bound is null, 'today', or a valid YYYY-MM-DD date.
fields fields, purpose, consent 1–8 typed fields, optional purpose text represented as a string or null, and consent details or null.

Questions are presented in sequence unless they carry logic (below). Older installed SDKs can be withheld surveys containing question types they do not support; verify your app's installed version when using newer types.

Exclusive choices and selected-option follow-ups

SDK 0.5.3 supports exclusive: true on a multiple-choice option, such as “None of these”. Selecting it clears the other selections; selecting an ordinary option clears the exclusive one. A question using an exclusive option must have min_selections: 1.

A single_choice question can set options_source_question_id to the ID of an earlier multiple_choice question. It then offers only the options the visitor selected there, excluding exclusive options. Its required options array can be empty or contain additional fixed choices with distinct IDs. The source choices plus fixed choices must fit within 32 options.

For example, ask which problems a visitor encountered, then which selected problem mattered most. Changing the earlier answer updates the follow-up choices. The SDK requests choice_logic=v1; older SDKs are not served surveys requiring this capability.

Logic and endings

Every question can carry an optional logic object, and the content an optional endings list.

Field Meaning
logic.show_when A condition on earlier answers. When it does not hold, the question is passed over.
logic.rules 1–16 rules of { when, to }, tried in order. The first match decides where the visitor goes.
logic.otherwise Where to go when no rule matches. Without it, the next question follows.
endings Up to 16 named endings of { id, kind, name, message } beside the default one. kind is 'completion' or 'screen_out'; message is a string or null for the thank-you text.

A destination (to, otherwise) is { type: 'question', id } for a later question, { type: 'ending', id } for a named ending, or { type: 'end' } for the default ending. Routes only go forward.

A condition is { type: 'answer', question_id, comparison }, or { type: 'all' | 'any', conditions }. The comparison's operator depends on the question it reads:

Question Operators
Any answered, skipped
single_choice is, is_not (one option ID in value); one_of, not_one_of (a list)
multiple_choice contains_any, contains_all, contains_none, exactly (a list of option IDs)
rating eq, gt, gte, lt, lte (a number in value); between (min and max)
text character count length_eq, length_gt, length_gte, length_lt, length_lte (a number in value); length_between (min and max)
text literal matching text_eq, text_not_eq, text_contains, text_not_contains, text_starts_with, text_not_starts_with, text_ends_with, text_not_ends_with (text in value)

Text conditions ignore leading and trailing whitespace and normalize Unicode to NFC. Character counts use Unicode code points, so a simple emoji counts once; a combined emoji can contain several code points. Text matching ignores letter case and treats punctuation literally. Counts range from 0 to 10,000, ranges include both ends, and text to match must not be blank. Skipped, unseen and blank answers never satisfy a text condition, including a negative one. Use skipped to test for a missing answer.

For example, add this logic to a clarification question after an open-text question whose ID is feedback. It is shown only when the previous answer has fewer than 12 characters:

json
{
  "show_when": {
    "type": "answer",
    "question_id": "feedback",
    "comparison": { "operator": "length_lt", "value": 12 }
  }
}

The original answer and the clarification are kept separately. Combine conditions with all or any, such as a low rating and a short explanation. A compatible SDK requests flow_text=v1; the API omits surveys using these comparisons from older SDKs.

A question the visitor never reached matches no comparison. A response that finishes with a screen_out ending is saved, counted apart from completions, and the visitor is not asked that survey again unless its frequency says to ask again after a screen-out. Publishing refuses logic that points to a missing question, option or ending, goes back to an earlier question, or reads an answer that comes later.

Rating styles

The default numbers style supports the full range. stars and hearts require a minimum of 1 and maximum of at most 7. smileys uses 1–3 or 1–5. thumbs and yes_no use 0–1.

labels, when provided, has one string per value in ascending order. It is required for smileys, thumbs and yes/no, so visitors know what each value means. The stored answer is always the chosen integer, regardless of style.

Choices and other answers

Each choice has a unique id and a label up to 500 characters. An optional image is { url, alt }; published image URLs must be HTTPS. At most one option can have other: true, which requests up to 500 characters of the visitor's own words. Responses retain the option ID and that text separately.

Typed fields

Each field is { id, type, label, required }. Supported types are name, email, phone, company, address and text; values are strings of at most 500 characters. Supported contact traits can prefill name, email, phone and company fields.

purpose explains why you are asking. consent is null or { label, link_label, link_url }. Link label and URL must either both be null or both supplied; published links must be HTTPS. When consent is configured, the visitor must tick it before those details are sent. This question-level consent is separate from your site's SDK storage consent flow.

Invitations and asker

An invitation requires style, heading, message, reward, minutes and decline_forever:

  • style is card, compact or question.
  • heading is up to 240 characters. message is up to 1000 or null; reward is up to 240 or null.
  • minutes is an integer from 1 to 60, or null to use the question-based estimate.
  • decline_forever enables the option to stop this survey for that visitor.

A question invitation needs a rating first question, or a listed single-choice first question with at most five options.

An optional asker is a person, { type: 'person', name, role, photo_url }, with nullable role and photo; or a character, { type: 'character', variant: 'pip', name, color }, with nullable six-digit hex color. Published photos use HTTPS. These options change presentation, not the question IDs or answer values.

Languages

Set language to the default language tag. translations maps up to 29 additional language tags to translated content; do not include the default language again.

A translation can contain title, description, thank_you, invitation text (heading, message, reward), an asker's role, and questions keyed by question ID. Question translations support prompt, endpoint labels, value labels, option labels in options, image descriptions in alts, matrix rows, typed fields, purpose, consent and consent_link. Maps refer to existing IDs; rating value labels are keyed by their number as a string.

Publishing checks that configured translations have the required text. Draft review markers in needs_review identify text that still needs attention. SDK language selection is described under Appearance and language.

Drafts, versions and responses

Create and update change the editable draft. Publish makes a validated version live. prompt get reports the current definition, publication state, revision and whether there are unpublished changes. Mutations require the current revision to prevent overwriting another edit.

Responses remain associated with the exact admitted survey version. Editing a question today does not reinterpret earlier answers. See SDK notifications for response values and CLI for lifecycle commands.