Question scripts and shared helpers
Use question scripts to run code when a question appears or when the participant leaves it. For calculations that control later branches, a JavaScript Flow step is usually easier to follow.
This guide assumes familiarity with JavaScript functions, asynchronous saves, and browser DOM elements.
Run code for one question
- Select the question in Content to open its settings.
- Select Custom JavaScript, then Enable custom JavaScript.
- Define
onLoad(question, variables),onUnload(question, variables), or both. - Test in Preview, including returning with Back.
question is the DOM element containing this question. variables reads available Flow, URL, and study values. The script also has globals and questionState for saved JSON data.
async function onLoad(question, variables) {
await questionState.init({visits: 0});
await questionState.set("visits", questionState.get("visits") + 1);
}
async function onUnload(question, variables) {
await globals.set("last_question_visits", questionState.get("visits"));
}
This records how often the question was visited and copies that count into response-wide data when leaving. Callbacks can use await; the survey waits for them and their saves during ordinary navigation.
To inspect the saved values, submit a published pilot response and check JavaScript · Questions and JavaScript · Globals in Results → Export preview.
onUnload is part of survey navigation. Do not rely on it to save data when someone closes a tab or the browser stops. Save important data as soon as it is available.
Keep temporary and saved state distinct
Top-level declarations in a question script keep their scope across visits while the survey stays open. A full reload recreates them. Use saved data for anything needed after reload or in exports.
For DOM changes, work within the question element. If you add event listeners or timers on load, remove or cancel them on unload to avoid duplicate behavior when the participant returns. Browser DOM changes alone do not save a survey answer.
Question scripts can call await variables.set(name, value) for declared Flow variables. They cannot use the Flow-only answers API or explicit Loop selectors. Return values from onLoad and onUnload are not calculation results.
Share a helper across the survey
In survey settings, find Survey JavaScript setup. Define helpers there without an enclosing function:
function addBonus(score, bonus) {
return score + bonus;
}
A JavaScript Flow calculation can then use that helper:
return addBonus(variables.get("base_score"), variables.get("bonus"));
Declare base_score and bonus as Numbers earlier in Flow and choose Number for the result. The helper is also available to question scripts.
Setup is reused as the participant moves between pages. Reloading or restarting Preview runs setup again; failed setup can also be retried. Do not use setup’s ordinary variables as permanent storage. Setup can use await globals.init(...) for defaults that preserve already saved values, but does not receive a question element or the question callback’s variables argument.
Preview and external actions
Preview runs the same scripts with separate in-memory data. External requests in your code still run. Check execution and errors before adding network requests or other actions that could be repeated.