Documentation

Text Question

When and Why to Use

Use this to collect open-ended responses where you want to capture thoughts, opinions, or unaided recall. It's ideal for:

  • Brand recall
  • Reasons behind choices
  • Open feedback

Includes built-in AI validation to ensure quality. Responses are scored 1-5, and if too weak, the respondent is prompted to clarify.

Use a Qualitative Text Question instead when the research objective requires adaptive follow-up questions based on the respondent's answers. A text question validates or clarifies one response; a qualitative text question conducts a bounded multi-turn interview.

Respondents get max_attempts chances (default 3) to meet the quality_threshold (default 3). On the final attempt, termination_threshold (default 1) decides whether a lower-quality response is accepted or the respondent is terminated — with the default of 1, no score causes termination. Set a custom_validator to use your own validation instead of AI scoring.

Chat Experience
  • Single-line or multiline input, depending on the short flag.
  • Inline validation appears after submission.
  • Retry prompt if response doesn't meet the quality threshold.
  • Multiple responses (number_of_responses / min_responses) are not available in the chat experience — they are supported only in the traditional experience.
Plain text
Markdown Many Options
Traditional Experience
  • Supports multi-response collection if number_of_responses > 1 (traditional experience only).
  • Respondents can enter several distinct answers before continuing.
  • AI validation is unavailable with multiple responses: leave quality_threshold, termination_threshold, and max_attempts at their defaults and omit validation_instructions. A custom_validator may still be used.
Single response and an imageMultiple responsesMobile optimizedMultiple responses, mobile optimized
Markdown ImagesMarkdown Many OptionsText Question Figure 01Multiple response text question mobile
Configuration Options
OptionTypeRequiredDefaultDescription
questionstringyes-The prompt shown to the user
imageMediaItemno-Optional image from s.media
image_sizetuple[int, int]no600x600Bounding box size of the image; if omitted, images render at 600x600
defaultstr, list[str], or list[list[str]]nogenerated textSimulated answer for test data. Use a string or a list of candidate strings for a single response; one full list response or a list of list-response candidates for multiple responses. Each simulated respondent picks one candidate at random
shortbooleannoFalseUse a compact text field (for names, labels, etc)
recodesdict[str, str]no-Optional text recodes (not often used here)
validation_instructionsstringno-AI instructions for what makes a valid response, scored on a scale of 1 to 5
quality_thresholdintno3Normal minimum passing score (1-5); lower-scoring responses trigger a clarification prompt
termination_thresholdintno1Minimum score accepted on the final attempt; a lower score terminates the survey. The default of 1 prevents score-based termination
max_attemptsintno3Maximum number of attempts before termination_threshold applies
custom_validatorCallable[[str | list[str]], str | None]no-Called with the parsed response (a string for one response, a list of strings for multiple); return an error message to reject it, otherwise None
number_of_responsesintno1Number of distinct answers to collect. Only supported in the traditional experience
min_responsesintno-Minimum number of answers required. Only supported in the traditional experience
number_secondsintno0Seconds to wait before allowing the respondent to continue
tagss.tag()no-Used to fill tokens in text and group questions in reports
idstringno-Optional stable identifier for this question
Example Code
s.text_question("When you think about cars, which brands immediately come to mind?")

With validation and image:

s.text_question(
    "What do you like about {brand} cars?",
    tags=s.tag(brand="Ford"),
    validation_instructions="Please provide a specific reason, not just 'they're good'",
    image=s.media.ford_logo,
)

With a custom validator:

known_brands = ["ford", "toyota", "honda", "tesla"]

s.text_question(
    "Name a car brand you would never consider buying",
    custom_validator=lambda x: "That doesn't sound like a brand name" if x.lower() not in known_brands else None,
)
Notes
  • AI validation is optional but enabled by default.
  • Termination is controlled by termination_threshold. The default of 1 accepts every score the 1-5 validator can produce, so no respondent is terminated unless you raise it.
  • custom_validator overrides AI validation entirely if provided.
  • A single response is returned as a StringResponse; multiple responses are returned as a ListResponse.