Skip to content
  • There are no suggestions because the search field is empty.

Custom scripting

Write JavaScript, or generate it with AI, to validate answers, rewrite questions, branch on calculations, and more.

Centiment surveys include built-in declarative tools: display logic, skip logic, choice display, and piping. For everything beyond that, custom scripting lets you write small JavaScript snippets that run while the respondent takes the survey.


Use scripting when you need to:

  • Validate a free-text answer against a custom rule (e.g. a phone-number format)

  • Reword a question dynamically based on an earlier answer

  • Show or hide options based on a runtime calculation

  • Auto-advance, jump to a specific question, or end early

  • Tag responses based on conditions                                                                  

                                                                                                                         
If your need is covered by built-in display or skip logic, use that. It's faster, easier to read, and doesn't need testing.


Enabling scripting

  1. Open your survey in the Build tab. 

  2. From the right sidebar, click More → Scripting.

  3. The Scripting panel opens. Use the toggle in the panel header to enable or disable scripting for the entire survey.

When scripting is disabled, your scripts stay saved but don't run. Re-enable any time.

Survey scripts vs question scripts

You can attach scripts at two levels:                                                                                                                      

  • Survey-level: runs once at survey start (`cs.onLoad`) or at completion (`cs.onComplete`). Best for survey-wide setup, tagging, or logic based on URL parameters.

  • Question-level: attached to a specific question. Runs when that question is shown (`cs.onShow`), when its answer changes (`cs.onAnswer`), when the respondent navigates back (`cs.onBack`), or when the answer is being validated for advancement (`cs.onValidate`).

Open a script via the Scripting panel menu, or for question scripts, click Custom script in the question's sidebar configuration.


Quick start

Open the Scripting panel, click Add script, pick the question you want to script, and paste this in:

cs.onValidate((qid, value) => {                                          
if (!value) return { valid: false, message: "This field is required." };  
     if (String(value).length < 10) {                                     
       return { valid: true, warning: "You can add more detail." };       
     }                                                                    
   }                                                                      
   return { valid: true };                                                
});                                                                      

Click Save. The script blocks advancement until the respondent enters at least one character, and shows a non-blocking warning if the answer is shorter than 10 characters.

Generate scripts with AI

If you'd rather not write JavaScript by hand, click Generate in the script editor toolbar. Describe what you want in plain English, for example:                                                                                                                         

  ▎ "Skip to question 5 if the user picks Other in this question."

  ▎ "When the survey starts, hide the email question if the URL parameter anonymous is set."

The generator builds a script using the available cs.* API. Review the result (the generated script preview appears below your prompt) and click Apply to insert it into the editor. Click Save to persist.

You can edit existing scripts the same way: open a question's script, click Generate, and describe the change you want. The generator is given your current script as context. There's a daily limit on AI generations per user.

The cs API at a glance

Every script has access to a global cs object with these capabilities:

  Lifecycle hooksonLoad, onComplete, onShow, onAnswer, onValidate, onBack

  Read & write answersgetAnswer(qid, type?), setAnswer(qid, value)

  Read & write variables: getVariable(id), setVariable(id, value)

  Modify questions at runtime: setQuestionText, hideQuestion, showQuestion, setRequired

  Modify options / rows / columns: hideOption, showOption, setOptionText, reorderOptions, plus row/col equivalents for matrix questions   

  Navigate: skipTo(qid), clickNext(), clickPrev(), disableNext(), enableNext()

  Tag the response: addTag("name"), removeTag("name")

  End the survey: complete(url?), disqualify({ quality, delete, url }), overquota(url?)

  Context: getDevice(), getLanguage(), getUrlParam(key), getStartTime(), elapsed(), getQuestionTiming(qid), getSessionId()

  Helpers: random(seed?), shuffle(arr, seed?), format(n, options), pipe(text), log(...args)

The script editor shows full type-aware autocomplete. Start typing cs. and press Ctrl+Space to see options with parameter hints. Use the Insert ID button in the toolbar to drop in question, option, or variable IDs without typing them by hand.


Common recipes

 Custom validation

cs.onValidate((qid, value) => {                                          
  if (!/^\d{5}$/.test(String(value ?? ""))) {                             
     return { valid: false, message: "Please enter a 5-digit ZIP code." };
  }                                                                       
  return { valid: true };                                                 
});                                                                      

 Conditional skip

cs.onValidate((qid, value) => {                            
  if (value === "OPT_NOT_INTERESTED") cs.skipTo("Q_END");   
  return { valid: true };                                   
});                                                        

 Auto-advance on selection

cs.onAnswer((qid, value) => {                               
  if (Array.isArray(value) && value.includes("OPT_AUTO")) {  
    cs.clickNext();                                          
  }                                                          
});                                                         

 Tag based on score

cs.onComplete(() => {                                      
  const nps = cs.getAnswer("Q_NPS", "net-promoter-score");  
  if (nps && nps.score >= 9) cs.addTag("promoter");         
});                                                        

 Pipe an earlier answer into a later question's title

cs.onShow((qid) => {                                        
  const name = cs.getAnswer("Q_NAME") ?? "there";            
  cs.setQuestionText(qid, `Hi ${name}, ready to continue?`); 
});                                                          

The Insert snippet button in the editor toolbar gives you ready-made templates for the most common patterns. Pick one and edit the IDs.

Testing your scripts

Click Preview in the script editor toolbar. It opens your survey in a new tab, scoped to the question you're editing. Open the browser developer console to see anything you log via cs.log(...).

Preview mode runs the same scripting engine as your live survey, so anything that works in preview works for respondents.


Limits and sandbox                                     

Scripts run in an isolated sandbox in the respondent's browser. To keep surveys fast and secure:

  • No network access: fetch, XMLHttpRequest, WebSockets, and similar are disabled.

  • No DOM access: window, document, navigator, and friends are disabled.

  • No timers: setTimeout, setInterval are disabled. Hook into Centiment's lifecycle events instead.

  • No dynamic code: eval, Function(), import(), and require() are disabled.

Scripts that try to use any of the above won't save and the editor will highlight the issue inline. There's a soft size limit per script. If your script is getting big, split the logic into multiple per-question scripts.

Troubleshooting

The script editor shows red squiggles: that's a syntax or banned-identifier error. Hover the squiggle for the message. Save is blocked until the script is clean.

My script saved but nothing happens: make sure scripting is enabled at the survey level (toggle in the Scripting panel header). Also check that you registered a hook (cs.onShow(...), cs.onValidate(...), etc.). Top-level code outside hooks runs once when the script loads, before the respondent sees the question.

cs.getAnswer(...) returns undefined: the respondent hasn't answered that question yet, or the question ID is wrong. Use Insert ID to grab IDs reliably.

An end-action (cs.complete, cs.disqualify, cs.overquota) fired but the survey continued: only the last terminal call inside a single hook wins. If multiple hooks call terminal actions, the latest one applied takes effect. 

My validation message doesn't show: make sure your onValidate handler returns an object: { valid: false, message: "..." } for blocking errors, or { valid: true, warning: "..." } for non-blocking notices.

If you're stuck, reach out to Centiment support with the survey UUID and the script you're trying to run.