Passer au contenu principal

Scripting

Aperçu

Le scripting permet de calculer la valeur finale d'une question profil avec du code, au lieu d'une sélection manuelle.

Utilisez cette fonctionnalité lorsque vous avez besoin d'une logique avancée (par exemple : calcul de score, segmentation, libellés de statut, ou classification dynamique selon les réponses précédentes).

Prérequis

Pour utiliser le scripting, configurez votre question avec tous les éléments suivants :

  • Type de question : Question profil
  • Mode : Automatic
  • Type du mode automatique : Scripting (Compute a value with a script)

Quand cette configuration est activée, une zone de texte dédiée apparaît (de type éditeur) où vous pouvez écrire le script qui calcule la valeur finale du répondant.

important

Les scripts s'exécutent dans un bac à sable sécurisé, sans accès au système de fichiers, au réseau ou aux classes Java, et sont limités à 500 ms de temps d'exécution. Gardez vos scripts courts et évitez les calculs répétés pour rester largement sous cette limite.

Références aux réponses précédentes

Les variables suivent un format structuré selon le type de question :

[Référence question].[Référence élément].[Propriété]

Questions profil / adaptatives

VariableDescriptionExemple de valeur
Q1.ANSWERRéponse(s) complète(s), séparées par une virgule"Oui" ou "Option A,Option B"
Q1.COUNTNombre de réponses sélectionnées1 ou 3
Q1.A001, Q1.A002, ...Nième réponse sélectionnée (index à partir de 1)"Option A"

Batterie d'items

I1, I2, ... correspondent aux références des items dans la batterie.

VariableDescriptionExemple de valeur
Q2.I1.ANSWERRéponse(s) de l'item I1"Satisfait"
Q2.I1.COUNTNombre de réponses pour l'item I11
Q2.I1.A001Première réponse de l'item I1"Satisfait"

Hotspot

Z1, Z2, ... correspondent aux références des zones dans le hotspot.

VariableDescriptionExemple de valeur
Q3.Z1.ANSWERRéponse de la zone Z1"Sélectionné"
Q3.Z1.COUNTNombre de réponses pour la zone Z11 ou 0

Questions ouvertes

F1, F2, ... correspondent aux références des champs dans la question ouverte.

VariableDescriptionExemple de valeur
Q4.F1.ANSWERRéponse du champ F1"Jean Dupont"
Q4.F2.ANSWERRéponse du champ F2"jean@email.com"

Questions R3M (3 mots / Expérience)

VariableDescriptionExemple de valeur
Q5.WORD1.ANSWERPremier mot"Innovation"
Q5.WORD2.ANSWERDeuxième mot"Qualité"
Q5.WORD3.ANSWERTroisième mot"Service"

Itérations de boucle

Quand une question est répétée dans une boucle, chaque itération expose son propre jeu de variables via la notation LOOPn (index à partir de 0) :

Q1.LOOP0.ANSWER  // première itération
Q1.LOOP1.ANSWER // deuxième itération
Q1.LOOP2.ANSWER // troisième itération

Fonctions d'accès aux données

Plutôt que de lire les variables brutes, utilisez les fonctions d'accès dédiées ci-dessous. Elles sont recommandées : plus lisibles, elles retournent null (ou 0 pour les comptages) en cas de réponse manquante ou de référence invalide, au lieu d'échouer.

Type de questionFonctionÉquivalent à
Profil / adaptativegetAnswer(questionRef)Q1.ANSWER
Profil / adaptativegetAnswer(questionRef, index)Q1.A001
Profil / adaptativegetAnswerCount(questionRef)Q1.COUNT
BatteriegetItemAnswer(questionRef, itemRef)Q2.I1.ANSWER
BatteriegetItemAnswer(questionRef, itemRef, index)Q2.I1.A001
BatteriegetItemAnswerCount(questionRef, itemRef)Q2.I1.COUNT
HotspotgetZoneAnswer(questionRef, zoneRef)Q3.Z1.ANSWER
HotspotgetZoneAnswer(questionRef, zoneRef, index)-
HotspotgetZoneAnswerCount(questionRef, zoneRef)Q3.Z1.COUNT
Question ouvertegetFieldAnswer(questionRef, fieldRef)Q4.F1.ANSWER
Question ouvertegetFieldAnswer(questionRef, fieldIndex)Q4.F1.ANSWER (par position)
R3M (3 mots)getWord1(questionRef) / getWord2(...) / getWord3(...)Q5.WORD1.ANSWER, etc.
R3M (3 mots)getWord(questionRef, wordRef)Q5.WORD1.ANSWER
getAnswer('Q1')                // → "Oui"
getAnswer('Q1', 1) // → "Option A"
getAnswerCount('Q1') // → 3

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

getZoneAnswer('Q3', 'Z1') // → "Sélectionné"
getZoneAnswerCount('Q3', 'Z1') // → 1

getFieldAnswer('Q4', 'F1') // → "Jean Dupont"
getFieldAnswer('Q4', 1) // → "Jean Dupont"

getWord1('Q5') // → "Innovation"
getWord('Q5', 'WORD2') // → "Qualité"
conseil

Une référence invalide ou hors limites (par exemple getItemAnswer('Q2', 'I999')) retourne null plutôt que de générer une erreur. Vérifiez toujours la valeur null avant de l'utiliser dans une comparaison ou un calcul.

Vérifier l'existence d'une réponse

Utilisez ces fonctions pour vérifier qu'une réponse existe avant de la lire, en alternative à la comparaison du résultat de getAnswer(...) (et des autres fonctions d'accès) à null.

FonctionDescription
hasAnswer(ref)Retourne true si ref a une réponse, c'est-à-dire si la variable ref.ANSWER existe
exists(ref)Retourne true si la variable exacte ref existe dans les données de réponse
hasAnswer('Q1')        // → true si Q1 a été répondu
hasAnswer('Q2.I1') // → true si l'item I1 de la batterie Q2 a été répondu
hasAnswer('Q3.Z1') // → true si la zone Z1 du hotspot Q3 a été répondue

exists('Q1.ANSWER') // → équivalent à hasAnswer('Q1')
exists('Q1.COUNT') // → true si la variable de comptage de Q1 existe
exists('Q1.A002') // → true si une deuxième réponse a été sélectionnée pour Q1
if (hasAnswer('Q1')) {
getAnswer('Q1');
} else {
'N/A';
}
conseil

hasAnswer(ref) est un raccourci pour exists(ref + '.ANSWER') et accepte n'importe quelle référence de question, d'item (Q2.I1), de zone (Q3.Z1) ou de champ (Q4.F1). exists(ref) est plus générique : elle vérifie n'importe laquelle des variables brutes décrites dans « Références aux réponses précédentes » ci-dessus (par exemple exists('Q1.A002') pour vérifier si une deuxième réponse a été sélectionnée).

Paramètres d'URL

Utilisez getQueryParameter(name) pour lire un paramètre de la chaîne de requête du lien d'enquête (par exemple un code de langue, un identifiant de panéliste, ou un paramètre de tracking ajouté à l'URL d'invitation).

FonctionDescription
getQueryParameter(name)Retourne la valeur du paramètre d'URL name, ou null s'il est absent
var lang = getQueryParameter('lang');
// Pour un lien d'enquête tel que https://.../survey?lang=en → "en"
var lang = getQueryParameter('lang');

if (lang == 'en') {
'English';
} else if (lang == 'fr') {
'Français';
} else {
'N/A';
}
conseil

Quand le paramètre est absent de l'URL, getQueryParameter retourne null. Vérifiez toujours la valeur null avant de l'utiliser dans une comparaison ou une concaténation.

Syntaxe de base de JexlScript

Le scripting est basé sur JexlScript. Si vous connaissez les structures de contrôle proches de JavaScript, vous reconnaîtrez rapidement la syntaxe.

Règles essentielles :

  • Terminer chaque instruction par ;
  • Utiliser var pour déclarer une variable
  • Utiliser if (...) { ... } pour les conditions
  • Utiliser else { ... } pour la logique alternative
  • Utiliser ==, !=, >, <, >=, <=, &&, ||, ! pour les comparaisons et tests logiques
  • Le résultat du script est la valeur de la dernière expression évaluée — un return explicite n'est pas requis, mais return ...; est également pris en charge

Exemple de script

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

var value = 'N/A';

if (genre == 'Homme' || genre == 'Femme') {
value = genre;

if (age > 45) {
value = value + ' - hors cible';
} else {
value = value + ' - dans la cible';
}
}

value

Ce que fait cet exemple :

  • Lit le genre depuis Q1 en texte
  • Lit l'âge depuis Q2 en entier, avec 0 par défaut si la valeur est manquante ou invalide
  • Construit un libellé uniquement pour les valeurs de genre attendues
  • Retourne N/A si aucune classification valide n'est possible

Fonctions de conversion

FonctionAlias françaisDescription
number(value)nombre(value)Convertit une valeur en nombre décimal
number(value, default)nombre(value, default)Idem, avec default utilisé si la conversion échoue
integer(value)entier(value)Convertit une valeur en nombre entier (tronque les décimales)
integer(value, default)entier(value, default)Idem, avec default utilisé si la conversion échoue
text(value)texte(value)Convertit une valeur en texte
number('42')        // → 42.0
number('abc', 0) // → 0 (valeur par défaut, 'abc' n'est pas un nombre)
integer('3.14') // → 3
text(42) // → "42"

Fonctions mathématiques

FonctionAlias françaisDescription
round(number)arrondi(number)Arrondit à l'entier le plus proche
max(a, b)-Retourne le plus grand des deux nombres
min(a, b)-Retourne le plus petit des deux nombres
abs(number)-Retourne la valeur absolue
modulo(a, b)-Retourne le reste de la division de a par b
exp(number)exponential(number) / exponentielle(number)Calcule l'exponentielle (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...

Fonctions de texte

FonctionAlias françaisDescription
length(text)longueur(text)Retourne la longueur d'un texte
trim(text)-Supprime les espaces en début et fin de texte
length('Bonjour')      // → 7
trim(' Bonjour ') // → "Bonjour"

Fonctions de date et d'heure

Ces fonctions donnent accès à la date/heure courante, permettent d'extraire ou de reformater une date/heure provenant d'une réponse, d'ajouter ou de soustraire une durée à une date, une heure, ou une valeur de date/heure arbitraire, et de calculer l'écart entre deux dates ou deux heures.

Composants de la date/heure courante

FonctionDescriptionExemple de valeur
day()Jour du mois courant17
month()Mois courant (1-12)8
year()Année courante2026
hour()Heure courante (0-23)14
minute()Minute courante32
second()Seconde courante5

Extraire un composant d'une date/heure donnée

Utilisez ces variantes pour extraire un composant d'une date/heure provenant d'une réponse (par exemple une date de naissance collectée dans une question ouverte), plutôt que de la date/heure courante. value est analysée selon format, puis le composant demandé est retourné.

FonctionDescriptionExemple
day(value, format)Jour du mois extrait de valueday('17/08/2026', 'dd/MM/yyyy')17
month(value, format)Mois (1-12) extrait de valuemonth('17/08/2026', 'dd/MM/yyyy')8
year(value, format)Année extraite de valueyear('17/08/2026', 'dd/MM/yyyy')2026
hour(value, format)Heure (0-23) extraite de valuehour('14:32:05', 'HH:mm:ss')14
minute(value, format)Minute extraite de valueminute('14:32:05', 'HH:mm:ss')32
second(value, format)Seconde extraite de valuesecond('14:32:05', 'HH:mm:ss')5
day('17/08/2026', 'dd/MM/yyyy')      // → 17
month('17/08/2026', 'dd/MM/yyyy') // → 8
year('17/08/2026', 'dd/MM/yyyy') // → 2026
hour('14:32:05', 'HH:mm:ss') // → 14
minute('14:32:05', 'HH:mm:ss') // → 32
second('14:32:05', 'HH:mm:ss') // → 5
conseil

day, month et year attendent une value contenant une date ; hour, minute et second attendent une value contenant une heure. format doit correspondre exactement à value.

Date/heure courante sous forme de texte

FonctionDescriptionExemple de valeur
date()Date courante, au format dd/MM/yyyy"17/08/2026"
date(format)Date courante, avec un format personnalisédate('yyyy-MM-dd')"2026-08-17"
time()Heure courante, au format HH:mm:ss"14:32:05"
time(format)Heure courante, avec un format personnalisétime('HH:mm')"14:32"
conseil

L'argument format suit la syntaxe des patterns Java DateTimeFormatter. Les lettres les plus courantes sont d/M/y pour jour/mois/année et H/m/s pour heure/minute/seconde (par exemple dd/MM/yyyy, yyyy-MM-dd, HH:mm:ss).

Analyser et reformater une date/heure donnée

date(value, format) et time(value, format) analysent value selon format et la retournent formatée de la même façon. Comme l'entrée et la sortie utilisent le même pattern, ces fonctions servent surtout à valider qu'une réponse correspond bien au format attendu avant de l'utiliser ailleurs dans le script.

FonctionDescriptionExemple
date(value, format)Analyse value comme une date selon format, la retourne formatée de la même façondate('2026-08-17', 'yyyy-MM-dd')"2026-08-17"
time(value, format)Analyse value comme une heure selon format, la retourne formatée de la même façontime('14:32:05', 'HH:mm:ss')"14:32:05"
date('2026-08-17', 'yyyy-MM-dd')   // → "2026-08-17"
time('14:32:05', 'HH:mm:ss') // → "14:32:05"

Ajouter une durée à la date/heure courante

Chaque fonction retourne la date (ou l'heure) courante décalée du montant indiqué, formatée en texte. L'argument format est optionnel et vaut par défaut dd/MM/yyyy pour les fonctions de date, HH:mm:ss pour les fonctions d'heure.

FonctionDescription
addDays(amount) / addDays(amount, format)Date courante + amount jours
addMonths(amount) / addMonths(amount, format)Date courante + amount mois
addYears(amount) / addYears(amount, format)Date courante + amount années
addHours(amount) / addHours(amount, format)Heure courante + amount heures
addMinutes(amount) / addMinutes(amount, format)Heure courante + amount minutes
addSeconds(amount) / addSeconds(amount, format)Heure courante + amount secondes

amount peut être négatif pour reculer dans le temps (par exemple addDays(-7) pour il y a une semaine).

addDays(7)                    // → dans une semaine, ex. "24/08/2026"
addDays(-30, 'yyyy-MM-dd') // → il y a 30 jours, ex. "2026-07-18"
addMonths(1) // → même jour le mois prochain
addYears(-18) // → 18 ans avant aujourd'hui (ex. un seuil de majorité)
addHours(2, 'HH:mm') // → heure courante + 2 heures, ex. "16:32"

Ajouter une durée à une date/heure arbitraire

add(value, format, amount, unit) analyse value selon format, ajoute amount de unit, puis retourne le résultat formaté de la même façon. Utilisez cette fonction pour décaler une date/heure provenant d'une réponse, plutôt que la date/heure courante.

  • format doit correspondre exactement à value (mêmes règles que pour date()/time()) et peut décrire une date, une heure, ou les deux.
  • unit accepte (indépendamment de la casse) : DAYS, MONTHS, YEARS, HOURS, MINUTES, SECONDS.
  • La fonction génère une erreur si value ne peut pas être analysée avec format, ou si unit ne s'applique pas à la valeur analysée (par exemple ajouter des HOURS à une valeur ne contenant qu'une date, sans partie horaire).
add('01/01/2026', 'dd/MM/yyyy', 3, 'MONTHS')     // → "01/04/2026"
add('23:50:00', 'HH:mm:ss', 20, 'MINUTES') // → "00:10:00"
add('01/01/2026 23:00', 'dd/MM/yyyy HH:mm', 2, 'HOURS') // → "02/01/2026 01:00"
avertissement

Passer une unité non reconnue (autre que DAYS, MONTHS, YEARS, HOURS, MINUTES, SECONDS) ou une value qui ne correspond pas à format arrête le script avec une erreur. Validez les valeurs issues de réponses ouvertes avant d'appeler add(...) sur celles-ci.

Écart entre deux dates ou deux heures

Ces fonctions retournent l'écart entre deux dates (ou deux heures), toutes deux analysées avec le même format, sous la forme d'un nombre entier dans l'unité indiquée.

FonctionDescriptionExemple
daysBetween(startDate, endDate, format)Nombre de jours complets entre startDate et endDatedaysBetween('01/01/2026', '10/01/2026', 'dd/MM/yyyy')9
monthsBetween(startDate, endDate, format)Nombre de mois complets entre startDate et endDatemonthsBetween('01/01/2026', '15/03/2026', 'dd/MM/yyyy')2
yearsBetween(startDate, endDate, format)Nombre d'années complètes entre startDate et endDateyearsBetween('15/03/2005', '17/08/2026', 'dd/MM/yyyy')21
hoursBetween(startHour, endHour, format)Nombre d'heures complètes entre startHour et endHourhoursBetween('08:00:00', '17:30:00', 'HH:mm:ss')9
minutesBetween(startHour, endHour, format)Nombre de minutes complètes entre startHour et endHourminutesBetween('08:00:00', '08:45:00', 'HH:mm:ss')45
secondsBetween(startHour, endHour, format)Nombre de secondes complètes entre startHour et endHoursecondsBetween('08:00:00', '08:00:30', 'HH:mm:ss')30
daysBetween('01/01/2026', '10/01/2026', 'dd/MM/yyyy')      // → 9
monthsBetween('01/01/2026', '15/03/2026', 'dd/MM/yyyy') // → 2
yearsBetween('15/03/2005', '17/08/2026', 'dd/MM/yyyy') // → 21
hoursBetween('08:00:00', '17:30:00', 'HH:mm:ss') // → 9
minutesBetween('08:00:00', '08:45:00', 'HH:mm:ss') // → 45
secondsBetween('08:00:00', '08:00:30', 'HH:mm:ss') // → 30
conseil

daysBetween, monthsBetween et yearsBetween attendent des valeurs de date ; hoursBetween, minutesBetween et secondsBetween attendent des valeurs d'heure. Les deux valeurs doivent utiliser le même format. Si endDate/endHour est antérieure à startDate/startHour, le résultat est négatif.

avertissement

Toutes les fonctions documentées ci-dessus qui analysent une value selon un format (day(value, format), month(value, format), year(value, format), hour(value, format), minute(value, format), second(value, format), date(value, format), time(value, format), add(...), et les fonctions *Between) génèrent une erreur si la valeur ne peut pas être analysée avec le format indiqué. Validez ou vérifiez les valeurs issues de réponses ouvertes avant de les appeler.

Exemples supplémentaires

Score numérique avec arrondi

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

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

avg

Conserver la valeur la plus élevée parmi plusieurs entrées

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

max(max(v1, v2), v3)

Score pondéré

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

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

round(score)

Message selon un seuil

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

if (score >= 80) {
'Excellent - ' + text(score) + '%';
} else if (score >= 60) {
'Bien - ' + text(score) + '%';
} else {
'En dessous de l\'objectif - ' + text(score) + '%';
}

Concaténation de plusieurs champs

var prenom = getFieldAnswer('Q_IDENTITE', 'F1');
var nom = getFieldAnswer('Q_IDENTITE', 'F2');
var ville = getFieldAnswer('Q_IDENTITE', 'F3');

prenom + ' ' + nom + ', ' + ville
// → "Jean Dupont, Paris"

Vérification de majorité à partir d'une date de naissance

Utilisez yearsBetween pour calculer l'âge directement, plutôt que de comparer des dates formatées sous forme de texte :

var dateNaissance = getFieldAnswer('Q_DATENAISSANCE', 'F1');  // ex. "2005-03-15"

if (dateNaissance == null) {
'N/A';
} else {
var age = yearsBetween(dateNaissance, date('yyyy-MM-dd'), 'yyyy-MM-dd');

if (age >= 18) {
'Majeur';
} else {
'Mineur';
}
}

Règles et limitations

Autorisé :

  • Conditions if / else
  • Opérateurs de comparaison (==, !=, <, >, <=, >=)
  • Opérateurs logiques (&&, ||, !)
  • Opérateurs arithmétiques (+, -, *, /, %)
  • Variables locales (var x = ...)
  • Appels de fonctions
  • Concaténation de texte (+)
  • Accès aux propriétés (.)
  • Littéraux (tableaux, objets)

Non autorisé :

  • Boucles while / for
  • Lambdas / fonctions anonymes
  • Création d'objets avec new
  • Accès aux classes Java
  • Import de bibliothèques
  • Modification des variables globales
avertissement

Les scripts sont limités à 500 ms de temps d'exécution et s'exécutent dans un bac à sable isolé, sans accès au système de fichiers ou au réseau. Seules les fonctions documentées et les variables de questions sont disponibles.

Bonnes pratiques

  • Initialisez d'abord une valeur de repli par défaut (par exemple "N/A")
  • Convertissez explicitement les valeurs (text(...), number(...), integer(...)) avant toute comparaison, en utilisant la variante avec valeur par défaut pour vous protéger des réponses manquantes
  • Vérifiez la valeur null avant utilisation, en particulier avec getItemAnswer, getZoneAnswer et getFieldAnswer, qui retournent null pour les références manquantes ou invalides
  • Utilisez hasAnswer(ref) ou exists(ref) pour vérifier qu'une réponse existe avant de la lire, en alternative à une vérification de null
  • Stockez les calculs répétés dans une variable plutôt que de les recalculer dans chaque branche
  • Gardez des scripts courts et lisibles pour rester sous la limite de 500 ms
  • Testez les cas limites (réponses vides, valeurs inattendues, réponses manquantes)
  • Vérifiez toujours que le script retourne une valeur dans chaque branche