Skip to main content

Scripting

Overview

Scripting lets you compute a final value for a Profile question using code instead of a manual selection.

Use this when you need advanced logic (for example: score computation, segmentation, status labels, or dynamic classification based on previous answers).

Prerequisites

To use scripting, configure your question with all of the following:

  • Question type: Profile question
  • Mode: Automatic
  • Automatic type: Scripting (Compute a value with a script)

When this setup is enabled, a dedicated text area appears (editor-like input) where you can write the script that calculates the respondent's final value.

important

Scripts run in a secure sandbox with no access to the file system, network, or Java classes, and are limited to 500ms of execution time. Keep scripts short and avoid repeated calculations to stay well under this limit.

Referencing previous answers

Variables follow a structured naming pattern based on the question type:

[Question ref].[Element ref].[Property]

Profile / adaptive questions

VariableDescriptionExample value
Q1.ANSWERFull answer(s), comma separated"Yes" or "Option A,Option B"
Q1.COUNTNumber of selected answers1 or 3
Q1.A001, Q1.A002, ...Nth selected answer (1-based index)"Option A"

Battery of items

I1, I2, ... refer to the item refs in the battery.

VariableDescriptionExample value
Q2.I1.ANSWERAnswer(s) for item I1"Satisfied"
Q2.I1.COUNTNumber of answers for item I11
Q2.I1.A001First answer of item I1"Satisfied"

Hotspot

Z1, Z2, ... refer to the zone refs in the hotspot.

VariableDescriptionExample value
Q3.Z1.ANSWERAnswer for zone Z1"Selected"
Q3.Z1.COUNTNumber of answers for zone Z11 or 0

Open questions

F1, F2, ... refer to the field refs in the open question.

VariableDescriptionExample value
Q4.F1.ANSWERAnswer of field F1"John Smith"
Q4.F2.ANSWERAnswer of field F2"john@email.com"

R3M questions (3 words / Experience)

VariableDescriptionExample value
Q5.WORD1.ANSWERFirst word"Innovation"
Q5.WORD2.ANSWERSecond word"Quality"
Q5.WORD3.ANSWERThird word"Service"

Loop iterations

When a question is repeated inside a loop, each iteration exposes its own set of variables using the LOOPn notation (0-based):

Q1.LOOP0.ANSWER  // first iteration
Q1.LOOP1.ANSWER // second iteration
Q1.LOOP2.ANSWER // third iteration

Data-access functions

Instead of reading raw variables, use the dedicated access functions below. They are recommended: they are more readable, and they resolve missing answers or invalid refs to null (or 0 for counts) instead of failing.

Question typeFunctionEquivalent to
Profile / adaptivegetAnswer(questionRef)Q1.ANSWER
Profile / adaptivegetAnswer(questionRef, index)Q1.A001
Profile / adaptivegetAnswerCount(questionRef)Q1.COUNT
BatterygetItemAnswer(questionRef, itemRef)Q2.I1.ANSWER
BatterygetItemAnswer(questionRef, itemRef, index)Q2.I1.A001
BatterygetItemAnswerCount(questionRef, itemRef)Q2.I1.COUNT
HotspotgetZoneAnswer(questionRef, zoneRef)Q3.Z1.ANSWER
HotspotgetZoneAnswer(questionRef, zoneRef, index)-
HotspotgetZoneAnswerCount(questionRef, zoneRef)Q3.Z1.COUNT
Open questiongetFieldAnswer(questionRef, fieldRef)Q4.F1.ANSWER
Open questiongetFieldAnswer(questionRef, fieldIndex)Q4.F1.ANSWER (by position)
R3M (3 words)getWord1(questionRef) / getWord2(...) / getWord3(...)Q5.WORD1.ANSWER, etc.
R3M (3 words)getWord(questionRef, wordRef)Q5.WORD1.ANSWER
getAnswer('Q1')                // → "Yes"
getAnswer('Q1', 1) // → "Option A"
getAnswerCount('Q1') // → 3

getItemAnswer('Q2', 'I1') // → "Satisfied"
getItemAnswerCount('Q2', 'I1') // → 2

getZoneAnswer('Q3', 'Z1') // → "Selected"
getZoneAnswerCount('Q3', 'Z1') // → 1

getFieldAnswer('Q4', 'F1') // → "John Smith"
getFieldAnswer('Q4', 1) // → "John Smith"

getWord1('Q5') // → "Innovation"
getWord('Q5', 'WORD2') // → "Quality"
tip

An invalid or out-of-range ref (for example getItemAnswer('Q2', 'I999')) returns null rather than raising an error. Always guard against null before using a value in a comparison or calculation.

JexlScript syntax basics

Scripting is based on JexlScript. If you are familiar with JavaScript-like control flow, you will quickly recognize the syntax.

Key syntax rules:

  • End each instruction with ;
  • Use var to declare variables
  • Use if (...) { ... } for conditions
  • Use else { ... } for alternative logic
  • Use ==, !=, >, <, >=, <=, &&, ||, ! for comparisons and logical tests
  • The script's result is the value of the last evaluated expression — no explicit return is required, though return ...; is also supported

Example script

var gender = text(getAnswer('Q1'));
var age = integer(getAnswer('Q2'), 0);

var value = 'N/A';

if (gender == 'Male' || gender == 'Female') {
value = gender;

if (age > 45) {
value = value + ' - out of target';
} else {
value = value + ' - in target';
}
}

value

What this example does:

  • Reads gender from Q1 as text
  • Reads age from Q2 as an integer, defaulting to 0 if missing or invalid
  • Builds a label only for expected gender values
  • Returns N/A when no valid classification can be computed

Conversion functions

FunctionFrench aliasDescription
number(value)nombre(value)Converts a value to a decimal number
number(value, default)nombre(value, default)Same, using default if the conversion fails
integer(value)entier(value)Converts a value to an integer (truncates decimals)
integer(value, default)entier(value, default)Same, using default if the conversion fails
text(value)texte(value)Converts a value to text
number('42')        // → 42.0
number('abc', 0) // → 0 (fallback, 'abc' is not a number)
integer('3.14') // → 3
text(42) // → "42"

Math functions

FunctionFrench aliasDescription
round(number)arrondi(number)Rounds to the nearest integer
max(a, b)-Returns the greater of two numbers
min(a, b)-Returns the lesser of two numbers
abs(number)-Returns the absolute value
modulo(a, b)-Returns the remainder of a divided by b
exp(number)exponential(number) / exponentielle(number)Computes the exponential (e^x)
round(3.7)     // → 4
max(10, 20) // → 20
min(10, 20) // → 10
abs(-42) // → 42
modulo(10, 3) // → 1
exp(1) // → 2.718281828...

Text functions

FunctionFrench aliasDescription
length(text)longueur(text)Returns the length of a text value
trim(text)-Removes leading and trailing whitespace
length('Hello')        // → 5
trim(' Hello ') // → "Hello"

Additional examples

Numeric score with rounding

var scoreA = number(getItemAnswer('Q3', 'I1'));
var scoreB = number(getItemAnswer('Q3', 'I2'));

var total = scoreA + scoreB;
var avg = round(total / 2);

avg

Keep the highest value from multiple inputs

var v1 = number(getAnswer('Q4'));
var v2 = number(getAnswer('Q5'));
var v3 = number(getAnswer('Q6'));

max(max(v1, v2), v3)

Weighted score

var note1 = number(getAnswer('Q_NOTE1'), 0);
var note2 = number(getAnswer('Q_NOTE2'), 0);
var note3 = number(getAnswer('Q_NOTE3'), 0);

// Weighting: 50% note1, 30% note2, 20% note3
var score = (note1 * 0.5) + (note2 * 0.3) + (note3 * 0.2);

round(score)

Message based on a threshold

var score = number(getAnswer('Q_SCORE'), 0);

if (score >= 80) {
'Excellent - ' + text(score) + '%';
} else if (score >= 60) {
'Good - ' + text(score) + '%';
} else {
'Below target - ' + text(score) + '%';
}

Concatenation of several fields

var firstName = getFieldAnswer('Q_IDENTITY', 'F1');
var lastName = getFieldAnswer('Q_IDENTITY', 'F2');
var city = getFieldAnswer('Q_IDENTITY', 'F3');

firstName + ' ' + lastName + ', ' + city
// → "John Smith, Paris"

Rules and limitations

Allowed:

  • if / else conditions
  • Comparison operators (==, !=, <, >, <=, >=)
  • Logical operators (&&, ||, !)
  • Arithmetic operators (+, -, *, /, %)
  • Local variables (var x = ...)
  • Function calls
  • Text concatenation (+)
  • Property access (.)
  • Literals (arrays, objects)

Not allowed:

  • while / for loops
  • Lambdas / anonymous functions
  • Object creation with new
  • Access to Java classes
  • Library imports
  • Modification of global variables
warning

Scripts are limited to 500ms of execution time and run in an isolated sandbox with no access to the file system or network. Only the documented functions and question variables are available.

Best practices

  • Initialize a default fallback value first (for example "N/A")
  • Convert values explicitly (text(...), number(...), integer(...)) before comparisons, using the default-value overload to guard against missing answers
  • Check for null before using a value, especially with getItemAnswer, getZoneAnswer, and getFieldAnswer, which return null for missing or invalid refs
  • Store repeated calculations in a variable instead of recomputing them in every branch
  • Keep scripts short and readable to stay within the 500ms timeout
  • Test edge cases (empty answers, unexpected values, missing responses)
  • Always verify that the script returns a value in every branch