Skip to content

Branching questionnaire

Route participants to different questionnaire pages depending on their answer to an earlier question.

Use this when later parts of a questionnaire only make sense for some participants, such as asking about coffee habits only of the people who drink coffee. The naive alternative, showing everyone every question with “if applicable” in the wording, fills the results with not applicable noise and pads the session for the very participants the questions do not concern. Routing sends each participant only to the pages that apply and merges everyone again for the shared closing questions. If ineligible participants should leave the study entirely rather than take a different path, use the screener pattern with an end destination instead.

typeheadresponseTyperesponseOptionsrequiredpageBreaklabelifthen
formWhich do you drink more often?radioCoffee;Tea11responseCode=2tea_section
formHow many cups of coffee do you drink on a typical day?dropdownNone;1 or 2;3 or 4;5 or more1
formWhen do you usually drink your first coffee?radioBefore breakfast;With breakfast;Later in the morning;Afternoon or later11wrap_up
formHow many cups of tea do you drink on a typical day?dropdownNone;1 or 2;3 or 4;5 or more1tea_section
formDo you usually take milk in your tea?radioYes;No;Depends on the tea11
formHow hard would you find it to give up caffeine for a week?likertNot at all hard;Slightly hard;Moderately hard;Extremely hard1wrap_up

Every row is a type=form row, and pageBreak set to 1 carves the run into four pages: the routing question alone, a coffee page, a tea page and a shared wrap up page. The break on the routing row is what makes the branching possible at all; without it, all the consecutive form rows would collapse onto a single page and there would be nothing left to route between.

The routing lives on the first row. if holds responseCode=2 and then holds tea_section: responseCode counts positions in responseOptions in the order you wrote them, so code 2 is Tea. Tea drinkers jump to the row labelled tea_section; when the condition does not match, nothing is jumped to, so coffee drinkers simply fall through to the next page. required set to exactly 1 guarantees the routing question is actually answered before the page can be submitted.

The coffee page ends with the second jump: its last row has a destination in then with if left blank, and a blank if with a filled in then takes the first destination unconditionally. That hop over the tea rows to wrap_up is what keeps coffee drinkers out of the tea section. The tea page needs no jump of its own, because the wrap up page is next in file order anyway.

The jump targets are named with label rather than row numbers, so inserting a question later does not silently re aim the branches. Two label gotchas to respect: a misspelled destination is indistinguishable from no jump, meaning a typo in wrap_up would quietly leak coffee drinkers into the tea page, and purely numeric labels are unreachable because numeric destinations are read as row numbers first.

  • Branch three or more ways by putting semicolon separated conditions in if paired with semicolon separated destinations in then; one extra destination at the end acts as the fallback when nothing matched.
  • Route on the answer text instead of its position with has(Tea) in if, which keeps working if you reorder the choices but breaks if you reword them; responseCode trades those risks the other way round.
  • Skip the routing question entirely when the information is already registered, by putting a participant detail condition such as %age%>=18 in if on the preceding row.
  • Send one branch out of the study instead of onward by using end as its destination in then, as in the screener pattern.