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.
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
| Variable | Description | Exemple de valeur |
|---|---|---|
Q1.ANSWER | Réponse(s) complète(s), séparées par une virgule | "Oui" ou "Option A,Option B" |
Q1.COUNT | Nombre de réponses sélectionnées | 1 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.
| Variable | Description | Exemple de valeur |
|---|---|---|
Q2.I1.ANSWER | Réponse(s) de l'item I1 | "Satisfait" |
Q2.I1.COUNT | Nombre de réponses pour l'item I1 | 1 |
Q2.I1.A001 | Première réponse de l'item I1 | "Satisfait" |
Hotspot
Z1, Z2, ... correspondent aux références des zones dans le hotspot.
| Variable | Description | Exemple de valeur |
|---|---|---|
Q3.Z1.ANSWER | Réponse de la zone Z1 | "Sélectionné" |
Q3.Z1.COUNT | Nombre de réponses pour la zone Z1 | 1 ou 0 |
Questions ouvertes
F1, F2, ... correspondent aux références des champs dans la question ouverte.
| Variable | Description | Exemple de valeur |
|---|---|---|
Q4.F1.ANSWER | Réponse du champ F1 | "Jean Dupont" |
Q4.F2.ANSWER | Réponse du champ F2 | "jean@email.com" |
Questions R3M (3 mots / Expérience)
| Variable | Description | Exemple de valeur |
|---|---|---|
Q5.WORD1.ANSWER | Premier mot | "Innovation" |
Q5.WORD2.ANSWER | Deuxième mot | "Qualité" |
Q5.WORD3.ANSWER | Troisiè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 question | Fonction | Équivalent à |
|---|---|---|
| Profil / adaptative | getAnswer(questionRef) | Q1.ANSWER |
| Profil / adaptative | getAnswer(questionRef, index) | Q1.A001 |
| Profil / adaptative | getAnswerCount(questionRef) | Q1.COUNT |
| Batterie | getItemAnswer(questionRef, itemRef) | Q2.I1.ANSWER |
| Batterie | getItemAnswer(questionRef, itemRef, index) | Q2.I1.A001 |
| Batterie | getItemAnswerCount(questionRef, itemRef) | Q2.I1.COUNT |
| Hotspot | getZoneAnswer(questionRef, zoneRef) | Q3.Z1.ANSWER |
| Hotspot | getZoneAnswer(questionRef, zoneRef, index) | - |
| Hotspot | getZoneAnswerCount(questionRef, zoneRef) | Q3.Z1.COUNT |
| Question ouverte | getFieldAnswer(questionRef, fieldRef) | Q4.F1.ANSWER |
| Question ouverte | getFieldAnswer(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é"
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.
| Fonction | Description |
|---|---|
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';
}
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).
| Fonction | Description |
|---|---|
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';
}
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
varpour 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
returnexplicite n'est pas requis, maisreturn ...;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
Q1en texte - Lit l'âge depuis
Q2en entier, avec0par défaut si la valeur est manquante ou invalide - Construit un libellé uniquement pour les valeurs de genre attendues
- Retourne
N/Asi aucune classification valide n'est possible
Fonctions de conversion
| Fonction | Alias français | Description |
|---|---|---|
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
| Fonction | Alias français | Description |
|---|---|---|
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
| Fonction | Alias français | Description |
|---|---|---|
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
| Fonction | Description | Exemple de valeur |
|---|---|---|
day() | Jour du mois courant | 17 |
month() | Mois courant (1-12) | 8 |
year() | Année courante | 2026 |
hour() | Heure courante (0-23) | 14 |
minute() | Minute courante | 32 |
second() | Seconde courante | 5 |
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é.
| Fonction | Description | Exemple |
|---|---|---|
day(value, format) | Jour du mois extrait de value | day('17/08/2026', 'dd/MM/yyyy') → 17 |
month(value, format) | Mois (1-12) extrait de value | month('17/08/2026', 'dd/MM/yyyy') → 8 |
year(value, format) | Année extraite de value | year('17/08/2026', 'dd/MM/yyyy') → 2026 |
hour(value, format) | Heure (0-23) extraite de value | hour('14:32:05', 'HH:mm:ss') → 14 |
minute(value, format) | Minute extraite de value | minute('14:32:05', 'HH:mm:ss') → 32 |
second(value, format) | Seconde extraite de value | second('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
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
| Fonction | Description | Exemple 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" |
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.
| Fonction | Description | Exemple |
|---|---|---|
date(value, format) | Analyse value comme une date selon format, la retourne formatée de la même façon | date('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çon | time('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.
| Fonction | Description |
|---|---|
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.
formatdoit correspondre exactement àvalue(mêmes règles que pourdate()/time()) et peut décrire une date, une heure, ou les deux.unitaccepte (indépendamment de la casse) :DAYS,MONTHS,YEARS,HOURS,MINUTES,SECONDS.- La fonction génère une erreur si
valuene peut pas être analysée avecformat, ou siunitne s'applique pas à la valeur analysée (par exemple ajouter desHOURSà 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"
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.
| Fonction | Description | Exemple |
|---|---|---|
daysBetween(startDate, endDate, format) | Nombre de jours complets entre startDate et endDate | daysBetween('01/01/2026', '10/01/2026', 'dd/MM/yyyy') → 9 |
monthsBetween(startDate, endDate, format) | Nombre de mois complets entre startDate et endDate | monthsBetween('01/01/2026', '15/03/2026', 'dd/MM/yyyy') → 2 |
yearsBetween(startDate, endDate, format) | Nombre d'années complètes entre startDate et endDate | yearsBetween('15/03/2005', '17/08/2026', 'dd/MM/yyyy') → 21 |
hoursBetween(startHour, endHour, format) | Nombre d'heures complètes entre startHour et endHour | hoursBetween('08:00:00', '17:30:00', 'HH:mm:ss') → 9 |
minutesBetween(startHour, endHour, format) | Nombre de minutes complètes entre startHour et endHour | minutesBetween('08:00:00', '08:45:00', 'HH:mm:ss') → 45 |
secondsBetween(startHour, endHour, format) | Nombre de secondes complètes entre startHour et endHour | secondsBetween('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
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.
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
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
nullavant utilisation, en particulier avecgetItemAnswer,getZoneAnsweretgetFieldAnswer, qui retournentnullpour les références manquantes ou invalides - Utilisez
hasAnswer(ref)ouexists(ref)pour vérifier qu'une réponse existe avant de la lire, en alternative à une vérification denull - 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