Survey syntax
Write a survey as a readable text file. Questions are headings, answers are bullets, and rules sit beside the question they affect.
A complete example
Save this as a UTF-8 .md file. In the survey editor, open Questionnaire Markdown to upload it, or download your current questionnaire to edit in any text editor.
# Do we actually agree?
Please answer honestly.
## q_agree. Do you agree with the decision?
[choose one]
[garble 20%]
- Yes
- No*
[skip to q_hours if q_agree == "Yes"]
## q_comment. What would you change?
[paragraph]
[show if q_agree == "No"]
## q_hours. How many hours did you spend on this project?
[number]
## q_thanks. Thank you for taking the time.
[explanation]
Here, a recorded Yes skips the comment and goes to the hours question. A recorded No shows the comment. Everyone then sees the thank-you card.
Questions and IDs
Start with # Title, then an optional introduction. Each question starts with ## id. Question text. Put its type on a separate line.
[choose one]- One choice from 2–20 distinct answers, each on a line beginning with - . This is the default if you omit the type.
[paragraph]- A written answer, up to 2,000 characters. It is recorded verbatim, without randomization.
[number]- A numeric answer. It is recorded as entered, without randomization.
[explanation]- An information card with a continue button and no answer. Paragraphs, numbers and explanation cards have no answer bullets.
[choose multiple]- Zero or more selections from 2–20 distinct answer bullets. Selections are recorded directly, without randomization. No stars or garble directive.
[required] / [optional]: Put one of these directives after the question type and before its answers. Single-choice questions are required by default; other answer types are optional. Required questions need an answer; required choose-multiple questions need at least one selection. Optional questions offer Skip question, which records no answer and does not randomize. Explanation cards have no required setting.
IDs such as q1 or q_agree stay with a question when you move it. Use unique IDs of up to 100 characters: A–Z, a–z, 0–9, underscores or hyphens. IDs are case-sensitive. end is reserved.
Rules refer to IDs, not question numbers or wording. If you rename an ID, update its references. Reordering preserves IDs, but rules must still respect the dependency order below.
Sensitive answers
Add * at the end of an answer to mark it sensitive: - No*. Use [garble 20%] before the answers to set the random-change rate. Omit it to use the default rate of 20%.
The rate must be at least 0% and less than 100%. A garble directive requires at least one starred answer. An ordinary question has no stars or garble directive; paragraph, number and choose-multiple answers are always unprotected.
Show and skip rules
[show if q_agree == "No"] shows this question only when the condition matches. Put show rules after the heading and before answers. They may refer only to earlier choose-one or choose-multiple questions.
All show rules on a question must match. Use at most one show rule per earlier question; use in to accept several answers from that question.
[skip to q_hours if q_agree == "Yes"] jumps after the current question. Put skip rules after its answers, or after the other directives for a question without answers. They may refer to the current or an earlier choose-one or choose-multiple question.
The first matching skip rule wins. With no match, continue in file order. Use a question ID as the destination, or end to finish. Loops are rejected. Keep type and garble directives before answers and skip rules.
Rules test the recorded answer, which may have been changed by randomization. They never test a protected original selection.
A skipped or unanswered question never matches a condition, including negative comparisons. A hidden question does not run its skip rules.
Operators
These four comparisons work in both show and skip rules. Examples below use a choose-one question with the ID q_role and answers Manager, Executive and Other.
| Condition | Matches when the recorded answer… |
|---|---|
q_role == "Manager" | is Manager. |
q_role != "Manager" | is any answer other than Manager. |
q_role in ["Manager", "Executive"] | is Manager or Executive. |
q_role not in ["Manager", "Executive"] | is neither Manager nor Executive. |
For choose-multiple questions, use the comparisons below. An empty selection matches the negative comparisons; a skipped or unanswered question never matches.
| Condition | Matches when… |
|---|---|
tools contains "Email" | Email is selected. |
tools not_contains "Email" | Email is not selected. |
tools contains_any ["Email", "Chat"] | At least one of Email or Chat is selected. |
tools contains_none ["Email", "Chat"] | Neither Email nor Chat is selected. |
Answer labels must match exactly, including case. In rules, use JSON double-quoted strings, or a nonempty list of distinct strings in square brackets. A star marking sensitivity is not part of the answer label.
There are no and/or expressions, numeric comparisons (<, >), text-answer tests, formulas, variables or functions. Syntax keywords stay in English in every language. Unknown IDs, labels, operators and directives are errors.
Text and escaping
Questions, explanations and answer labels support bold, italic, inline code and line breaks. Questions and explanations also support paragraphs, bulleted lists and numbered lists. HTML, links and images stay plain text. For a multiline title, question or answer in this file, put each continuation immediately after it, indented by two spaces.
In the editor, type **bold** or *italic* directly. Markdown downloads escape these formatting stars to keep them separate from the final sensitive-answer marker. Importing the download restores both the formatting and protection settings.
## q_comment. What would you change?
Think about the past week.
[paragraph]
Use \* for a literal star and \\ for a backslash. Other ASCII punctuation can also be escaped. Use \s for a space at a line boundary and \t for a tab. A line containing only \ represents an empty line within text; indent it for an empty continuation.
Inside a rule’s quoted label, use JSON escapes instead: \" for a quote, \\ for a backslash and \n for a newline. Unindented prose inside a question and unknown escapes are rejected.
Files and limits
Downloads preserve the title, introduction, IDs, question order, exact wording, types, stars, rates and rules. Uploading and downloading again preserves the questionnaire; spacing between blocks and omitted type markers may be standardized.
Sender details, survey notices, response periods and responses are separate from this file. Publishing creates a fixed survey: editing a file later does not change an already published survey.
Exported files begin with <!-- strudl:questionnaire v1 -->. You may omit this version comment when writing a file. Other versions are rejected. Built-in template files use the same syntax after a short YAML catalog header; normal questionnaire files need no header.
- At most 50 questions or information cards, and 20 answers per choose-one question.
- Up to 200 characters in the title, 2,000 in the introduction, 1,000 in a question and 200 in an answer label.
- Both the UTF-8 file and the normalized questionnaire data must fit within 256 KiB.
Uploads validate before replacing your draft. Invalid files leave it intact. Downloading your current questionnaire is a useful starting point for further edits.