Format d’Enquête Ouvert
Un format ouvert, basé sur JSON, pour définir des enquêtes et des formulaires. Utilisé par YourOpinion.is et libre d’implémentation pour tous.
Version actuelle : 1.0 (Publiée le 15 novembre 2025)
Télécharger la Spécification
- Schéma JSON - Définition du format lisible par machine
- Markdown - Documentation lisible par l’homme (optimisée pour les LLM)
Introduction
Le Format d’Enquête Ouvert fournit une méthode standardisée pour définir des enquêtes, des questionnaires et des formulaires en tant qu’objets JSON. Ce format permet :
- Portabilité - Déplacer des enquêtes entre différentes plateformes et outils
- Contrôle de version - Suivre les modifications d’une enquête avec des outils de comparaison (diff) standards
- Génération programmatique - Créer des enquêtes dynamiquement à partir de code
- Compatibilité avec les LLM - Les assistants IA peuvent facilement créer et modifier des enquêtes
Concepts Fondamentaux
Collections (Pages)
Les enquêtes sont organisées en collections, qui fonctionnent comme des pages ou des sections. Chaque enquête doit contenir au moins une collection.
Éléments
Composants individuels au sein d’une collection, tels que :
- Questions (saisie de texte, choix multiples, évaluations, etc.)
- Blocs de contenu (texte Markdown, images)
- Éléments de contrôle de flux (logique conditionnelle, sauts de page)
Ressources
Composants réutilisables pouvant être référencés par plusieurs questions :
- Listes d’options (pour les questions à sélection)
- Échelles d’évaluation
- Ressources partagées
Structure du Document
Une enquête est représentée comme un objet JSON avec la structure suivante :
{
"$schema": "https://youropinion.is/json-schema/1.0",
"$readme": "https://youropinion.is/docs/survey-format.md",
"collections": {
"collection-id-1": {
"name": "Nom de la Collection",
"elements": {
"element-id-1": {
"type": "Markdown",
"data": {
/* Données spécifiques à l'élément */
}
}
},
"displayOrder": ["element-id-1"]
}
},
"displayOrder": ["collection-id-1"],
"assets": {
"asset-id-1": {
"type": "options",
"data": {
/* Données spécifiques à la ressource */
}
}
}
}
Propriétés de Premier Niveau
$schema (optionnel)
URL vers la définition du Schéma JSON pour la validation :
"$schema": "https://youropinion.is/json-schema/1.0"
$readme (optionnel)
URL vers la documentation lisible par l’homme :
"$readme": "https://youropinion.is/docs/survey-format.md"
collections (obligatoire)
Objet contenant les pages/sections de l’enquête. Chaque clé est un ID de collection unique :
"collections": {
"welcome": {
"name": "Page d'accueil",
"elements": { /* ... */ },
"displayOrder": ["intro", "consent"]
},
"questions": {
"name": "Questions principales",
"elements": { /* ... */ },
"displayOrder": ["q1", "q2", "q3"]
}
}
Propriétés de la Collection :
name(chaîne, optionnel) - Nom lisible par l’homme pour la collection (non affiché aux utilisateurs, utilisé pour référence)condition(objet, optionnel) - Logique conditionnelle pour déterminer si cette collection doit être affichée (voir la section Logique Conditionnelle)elements(objet) - Contient les éléments de cette collection. Chaque clé est un ID d’élément uniquedisplayOrder(tableau) - Tableau d’ID d’éléments définissant l’ordre d’affichage
Important : Le tableau displayOrder agit à la fois comme un filtre et un séquenceur :
- Seuls les éléments listés dans
displayOrderseront affichés. - Les éléments non présents dans
displayOrderrestent dans la définition mais sont masqués. - Inclure un ID d’élément inexistant provoquera une erreur.
displayOrder (obligatoire)
Tableau spécifiant l’ordre des collections :
"displayOrder": ["welcome", "questions", "thank-you"]
Les mêmes règles de filtrage s’appliquent : seules les collections listées ici seront affichées.
assets (optionnel)
Composants réutilisables référencés par plusieurs éléments. Les ressources réduisent la duplication et facilitent la maintenance des enquêtes.
Types de ressources :
options- Listes d’options réutilisables pour les questionsSelectOne/SelectManyordinal-scale- Échelles étiquetées réutilisables pour les questionsOrdinalScaleinterval-scale- Échelles numériques réutilisables pour les questionsIntervalScale
Exemple - Ressource d’options :
"assets": {
"color-options": {
"type": "options",
"name": "Options de couleur",
"data": {
"options": {
"red": { "label": "Rouge" },
"blue": { "label": "Bleu" },
"green": { "label": "Vert" },
"yellow": { "label": "Jaune" }
},
"displayOrder": ["red", "blue", "green", "yellow"]
}
},
"satisfaction-scale": {
"type": "ordinal-scale",
"name": "Échelle de satisfaction standard",
"data": {
"labels": {
"1": "Très insatisfait",
"2": "Insatisfait",
"3": "Neutre",
"4": "Satisfait",
"5": "Très satisfait"
}
}
},
"nps-scale": {
"type": "interval-scale",
"name": "Échelle Net Promoter Score (NPS)",
"data": {
"start": 0,
"end": 10,
"labels": {
"start": "Peu probable",
"end": "Très probable"
}
}
}
}
Tous les types de ressources nécessitent :
type- Type de ressource :"options","ordinal-scale", ou"interval-scale"name- Nom lisible par l’homme à des fins de documentationdata- Structure de données spécifique au type
Les ressources peuvent être référencées en utilisant des références JSON (voir la section Références JSON).
Types d’Éléments
Les éléments sont les blocs de construction de votre enquête. Chaque élément a une propriété type et data. Tous les éléments peuvent optionnellement inclure un objet extensions pour des métadonnées personnalisées (non utilisé par le moteur de rendu standard).
Types d’éléments disponibles :
| Type | Catégorie | Description |
|---|---|---|
Markdown | Contenu | Afficher du texte et du contenu formatés |
FlowControl | Contrôle | Logique conditionnelle et navigation |
String | Question | Saisie de texte (une ou plusieurs lignes) |
Number | Question | Saisie numérique |
Date | Question | Sélecteur de date |
Boolean | Question | Case à cocher Oui/Non |
SelectOne | Question | Choix unique parmi des options (boutons radio) |
SelectMany | Question | Choix multiples parmi des options (cases à cocher) |
IntervalScale | Question | Échelle d’évaluation numérique (ex. : 0-10 pour le NPS, 1-5 pour la satisfaction) |
OrdinalScale | Question | Échelle d’évaluation étiquetée (ex. : de « Fortement en désaccord » à « Fortement d’accord ») |
Payment | Question | Élément de traitement de paiement |
Éléments de Contenu
Markdown
Affiche du texte formaté, des titres, des listes et d’autres contenus en utilisant la syntaxe Markdown.
{
"type": "Markdown",
"data": {
"markdown": "# Bienvenue !\n\nMerci de participer à notre enquête.\n\n- Veuillez répondre honnêtement\n- Toutes les réponses sont anonymes"
}
}
Markdown pris en charge :
- Titres (
#,##,###) - Listes (ordonnées et non ordonnées)
- Gras (
**texte**) et italique (*texte*) - Liens (
[texte](url)) - Blocs de code
FlowControl
Contrôle le flux de l’enquête avec une logique conditionnelle et de la navigation.
{
"type": "FlowControl",
"data": {
"condition": {
/* Optionnel - Voir la section Logique Conditionnelle */
},
"action": {
"type": "survey-finish" // Options : "survey-finish" ou "page-finish"
}
}
}
Types d’Action :
survey-finish- Termine l’enquête immédiatementpage-finish- Termine la page actuelle et passe à la suivante
Pour des informations détaillées sur la structure des conditions et des exemples, voir la section Logique Conditionnelle ci-dessous.
Types de Questions
Toutes les questions partagent ces propriétés communes :
{
"type": "QuestionType",
"data": {
"label": "Le texte de votre question ici",
"required": "yes", // Optionnel : "yes", "no", ou "suggested" (par défaut : "no")
"markdown": "Texte d'aide" // Optionnel : contexte additionnel en Markdown
}
}
Propriétés communes :
label(chaîne, obligatoire) - Le texte de la question affiché aux utilisateursrequired(chaîne, optionnel) - Indique si une réponse est requise :"yes","no", ou"suggested"(affiché comme optionnel mais encouragé)markdown(chaîne, optionnel) - Texte d’aide ou description supplémentaire au format MarkdowndefaultValue(tout type, optionnel) - Valeur pré-remplie pour la question
String
Saisie de texte sur une ou plusieurs lignes.
{
"type": "String",
"data": {
"label": "Quel est votre nom ?",
"placeholder": "Entrez votre nom complet", // Optionnel
"multiline": false, // Optionnel : true pour une zone de texte
"required": "yes"
}
}
Number
Saisie numérique avec validation optionnelle.
{
"type": "Number",
"data": {
"label": "Combien d'employés ?",
"min": 1, // Optionnel : valeur minimale
"max": 1000, // Optionnel : valeur maximale
"step": 1, // Optionnel : taille de l'incrément (par défaut : 1)
"required": "yes"
}
}
Propriétés :
min(nombre, optionnel) - Valeur minimale autoriséemax(nombre, optionnel) - Valeur maximale autoriséestep(nombre, optionnel) - Taille de l’incrément pour la validation de la saisie (par défaut : 1)
Date
Sélecteur de date avec niveau de précision et contraintes min/max optionnels.
{
"type": "Date",
"data": {
"label": "Quand nous avez-vous rejoints ?",
"required": "suggested",
"accuracy": "day", // Optionnel : "day", "month", ou "year" (par défaut : "day")
"min": "2020-01-01", // Optionnel : date la plus ancienne sélectionnable
"max": "2025-12-31" // Optionnel : date la plus récente sélectionnable
}
}
Propriétés :
accuracy(chaîne, optionnel) - Niveau de précision de la date :"day"- Sélecteur de date complet avec calendrier (par défaut)"month"- Sélection du mois et de l’année via des menus déroulants"year"- Sélection de l’année uniquement via un menu déroulant
min(chaîne, optionnel) - Date la plus ancienne sélectionnable. Peut être :- Une chaîne de date ISO (ex. :
"2020-01-01") - Une chaîne de temps relatif (ex. :
"+ 3 months","now","- 1 year")
- Une chaîne de date ISO (ex. :
max(chaîne, optionnel) - Date la plus récente sélectionnable. Mêmes options de format quemin.
Boolean
Case à cocher Oui/Non. La valeur par défaut est false (décochée).
{
"type": "Boolean",
"data": {
"label": "Termes et Conditions",
"description": "J'accepte les termes et conditions" // Affiché à côté de la case à cocher
}
}
SelectOne
Question à choix multiple (boutons radio) - les utilisateurs sélectionnent une seule option.
{
"type": "SelectOne",
"data": {
"label": "Quelle est votre couleur préférée ?",
"required": "yes",
"options": {
"options": {
"red": { "label": "Rouge" },
"blue": { "label": "Bleu" },
"green": { "label": "Vert" }
},
"displayOrder": ["red", "blue", "green"]
}
}
}
Utilisation de références de ressources :
{
"type": "SelectOne",
"data": {
"label": "Choisissez une couleur",
"options": { "$ref": "#/assets/color-options/data" }
}
}
SelectMany
Question à choix multiple (cases à cocher) - les utilisateurs peuvent sélectionner plusieurs options.
{
"type": "SelectMany",
"data": {
"label": "Quels systèmes d'exploitation utilisez-vous ?",
"required": "yes",
"options": {
"options": {
"windows": { "label": "Windows" },
"macos": { "label": "macOS" },
"linux": { "label": "Linux" }
},
"displayOrder": ["windows", "macos", "linux"]
},
"other": true, // Optionnel : ajoute une option "Autre" avec un champ de saisie de texte
"minSelections": 1, // Optionnel : nombre minimum de sélections requises
"maxSelections": 3 // Optionnel : nombre maximum de sélections autorisées
}
}
IntervalScale
Échelle d’évaluation numérique avec une plage définie (ex. : 0-10 pour le NPS, 1-5 pour la satisfaction). Couramment utilisée pour :
- Net Promoter Score (NPS) : échelle de 0 à 10
- Évaluations de satisfaction : échelle de 1 à 5 ou de 1 à 7
- Questions de probabilité : échelle de 0 à 10
{
"type": "IntervalScale",
"data": {
"label": "Quelle est la probabilité que vous nous recommandiez à un ami ?",
"required": "yes",
"scale": {
"start": 0, // Numéro de début de l'échelle
"end": 10, // Numéro de fin de l'échelle
"labels": {
// Étiquettes pour les points de début et de fin (obligatoires)
"start": "Pas du tout probable",
"end": "Extrêmement probable"
}
}
}
}
Cas d’utilisation courants :
// Net Promoter Score (NPS)
{
"type": "IntervalScale",
"data": {
"label": "Quelle est la probabilité que vous nous recommandiez ?",
"scale": {
"start": 0,
"end": 10,
"labels": {
"start": "Peu probable",
"end": "Très probable"
}
}
}
}
// Échelle de satisfaction à 5 points
{
"type": "IntervalScale",
"data": {
"label": "Dans quelle mesure êtes-vous satisfait de notre service ?",
"scale": {
"start": 1,
"end": 5,
"labels": {
"start": "Très insatisfait",
"end": "Très satisfait"
}
}
}
}
Affichage : Affiche une échelle horizontale avec des numéros cliquables. Les étiquettes apparaissent sous les points de début et de fin.
OrdinalScale
Échelle d’évaluation étiquetée où chaque point a une étiquette personnalisée. Idéal pour :
- Échelles de Likert avec une formulation spécifique pour chaque point
- Échelles d’accord (Fortement en désaccord → Fortement d’accord)
- Échelles de fréquence (Jamais → Toujours)
- Échelles d’évaluation personnalisées avec des étiquettes significatives
{
"type": "OrdinalScale",
"data": {
"label": "Dans quelle mesure êtes-vous satisfait de votre poste ?",
"required": "yes",
"scale": {
"labels": {
"1": "Très insatisfait",
"2": "Insatisfait",
"3": "Neutre",
"4": "Satisfait",
"5": "Très satisfait"
}
}
}
}
Cas d’utilisation courants :
// Échelle d'accord de type Likert
{
"type": "OrdinalScale",
"data": {
"label": "Le produit a répondu à mes attentes.",
"scale": {
"labels": {
"1": "Fortement en désaccord",
"2": "En désaccord",
"3": "Ni d'accord ni en désaccord",
"4": "D'accord",
"5": "Fortement d'accord"
}
}
}
}
// Échelle de fréquence
{
"type": "OrdinalScale",
"data": {
"label": "À quelle fréquence utilisez-vous notre produit ?",
"scale": {
"labels": {
"1": "Jamais",
"2": "Rarement",
"3": "Parfois",
"4": "Souvent",
"5": "Toujours"
}
}
}
}
Affichage : Affiche des boutons ou des options étiquetés. Chaque étiquette est affichée entièrement, rendant l’échelle auto-explicative.
IntervalScale vs OrdinalScale :
- Utilisez IntervalScale lorsque les chiffres eux-mêmes ont une signification (0-10, 1-5).
- Utilisez OrdinalScale lorsque vous avez besoin d’étiquettes personnalisées pour chaque point.
- L’élément
IntervalScaleest plus compact ; l’élémentOrdinalScaleest plus descriptif.
Payment
Collecte les informations de paiement et traite les transactions. S’intègre avec les fournisseurs de paiement configurés dans les paramètres de votre enquête.
{
"type": "Payment",
"data": {
"label": "Paiement",
"required": "yes",
"amount": {
"value": 29.99,
"currency": "USD"
},
"captureMethod": "automatic" // Optionnel : "immediate", "manual", ou "automatic"
}
}
Propriétés :
amount(objet, obligatoire) - Montant du paiement avecvalue(nombre) etcurrency(code à 3 lettres, ex. : “USD”, “EUR”, “GBP”)captureMethod(chaîne, optionnel) - Quand capturer le paiement :"immediate"- Capturer le paiement immédiatement lors de la soumission de l’enquête"manual"- Nécessite une capture manuelle via votre tableau de bord de paiement"automatic"- Capture automatiquement lorsque l’enquête est terminée (par défaut)
Remarque : Le traitement des paiements nécessite qu’un fournisseur de paiement soit configuré dans les paramètres de votre canal. Les devises et méthodes de paiement prises en charge dépendent de la configuration de votre fournisseur.
Références JSON
Réduisez la duplication en référençant des composants réutilisables. Les références utilisent ce format :
{ "$ref": "[<emplacement>]#<chemin>" }
emplacement- URL vers le document source (vide = document actuel)chemin- Chemin depuis la racine du document en utilisant des séparateurs/
Exemple - Duplication en ligne :
{
"question-1": {
"type": "SelectOne",
"data": {
"label": "Couleur préférée ?",
"options": {
"options": {
"red": { "label": "Rouge" },
"blue": { "label": "Bleu" }
},
"displayOrder": ["red", "blue"]
}
}
},
"question-2": {
"type": "SelectOne",
"data": {
"label": "Couleur la moins appréciée ?",
"options": {
"options": {
"red": { "label": "Rouge" },
"blue": { "label": "Bleu" }
},
"displayOrder": ["red", "blue"]
}
}
}
}
Mieux - En utilisant des ressources :
{
"collections": {
"main": {
"elements": {
"question-1": {
"type": "SelectOne",
"data": {
"label": "Couleur préférée ?",
"options": { "$ref": "#/assets/colors/data" }
}
},
"question-2": {
"type": "SelectOne",
"data": {
"label": "Couleur la moins appréciée ?",
"options": { "$ref": "#/assets/colors/data" }
}
}
},
"displayOrder": ["question-1", "question-2"]
}
},
"assets": {
"colors": {
"type": "options",
"data": {
"options": {
"red": { "label": "Rouge" },
"blue": { "label": "Bleu" }
},
"displayOrder": ["red", "blue"]
}
}
}
}
Avantages :
- Source de vérité unique
- Maintenance plus facile
- Meilleures comparaisons (diffs) pour le contrôle de version
- Taille de fichier réduite
Logique Conditionnelle
La logique conditionnelle vous permet de créer des enquêtes dynamiques qui s’adaptent en fonction des réponses de l’utilisateur. Les conditions peuvent être utilisées de deux manières :
1. Conditions au niveau de la collection
Afficher ou masquer des pages entières en fonction de conditions. Si la condition d’une collection est évaluée à false, la page entière est sautée et l’exécution passe à la collection suivante.
{
"collections": {
"follow-up": {
"name": "Questions de suivi",
"condition": {
"type": "condition",
"fact": "questions/nps-score",
"operator": "lt",
"compare": { "value": 7 }
},
"elements": {
/* ... */
},
"displayOrder": ["question-1"]
}
}
}
Dans cet exemple, la page “Questions de suivi” ne s’affiche que si le score NPS est inférieur à 7.
2. Éléments FlowControl
Contrôler le flux de l’enquête au sein d’une page en utilisant les éléments FlowControl. Lorsque la condition est évaluée à true, l’action spécifiée est exécutée.
Actions disponibles :
survey-finish- Termine l’enquête immédiatement (saute toutes les pages restantes)page-finish- Termine la page actuelle et passe à la suivante (saute les éléments restants sur la page actuelle)
{
"type": "FlowControl",
"data": {
"condition": {
"type": "condition",
"fact": "questions/satisfaction",
"operator": "eq",
"compare": { "value": "very-satisfied" }
},
"action": {
"type": "page-finish"
}
}
}
Remarque : Si aucune condition n’est fournie, l’action s’exécute toujours lorsque l’élément est atteint.
Structure d’une condition
Les conditions sont définies comme un arbre binaire avec deux types de nœuds :
1. Conditions de comparaison
Comparer un fait (réponse à l’enquête) à une valeur ou à un autre fait.
{
"type": "condition",
"fact": "questions/age",
"operator": "gt",
"compare": { "value": 18 }
}
Propriétés :
type- Toujours"condition"pour les comparaisonsfact(chaîne) - La référence de l’élément au format ‘collection-id/element-id’ dont la valeur doit être lueoperator(chaîne) - Opérateur de comparaison (voir les opérateurs ci-dessous)compare(objet, optionnel) - Ce à quoi comparer :{ "value": <any> }- Comparer à une valeur littérale{ "fact": "<collection-id>/<element-id>" }- Comparer à la valeur d’un autre élément- Non requis pour les opérateurs comme
"exists"ou"true"
not(booléen, optionnel) - Inverser le résultat (par défaut :false)
Opérateurs pris en charge par type d’élément :
Number, IntervalScale, OrdinalScale, Date :
"eq"- Égal à"gt"- Supérieur à"gte"- Supérieur ou égal à"lt"- Inférieur à"lte"- Inférieur ou égal à"exists"- A une valeur (pas decomparenécessaire)
String :
"eq"- Égal à"contains"- La chaîne contient la valeur"exists"- A une valeur (pas decomparenécessaire)
Boolean :
"true"- La valeur est vraie (pas decomparenécessaire)"exists"- A une valeur (pas decomparenécessaire)
SelectOne :
"eq"- Égal à une option spécifique"in"- Est l’une des multiples options (la valeur de comparaison doit être un tableau de valeurs)"exists"- A une valeur (pas decomparenécessaire)
SelectMany :
"eq"- Correspond exactement à l’ensemble des options"exists"- A au moins une valeur (pas decomparenécessaire)
2. Conditions en chaîne
Combiner plusieurs conditions en utilisant des opérateurs logiques.
{
"type": "all",
"items": [
{
"type": "condition",
"fact": "questions/age",
"operator": "gt",
"compare": { "value": 18 }
},
{
"type": "condition",
"fact": "questions/country",
"operator": "eq",
"compare": { "value": "US" }
}
]
}
Propriétés :
type- Opérateur logique :"all"- Toutes les conditions doivent être vraies (logique ET)"any"- Au moins une condition doit être vraie (logique OU)
items(tableau) - Tableau de conditions (peuvent être des comparaisons ou des chaînes imbriquées)not(booléen, optionnel) - Inverser le résultat de toute la chaînename(chaîne, optionnel) - Étiquette lisible par l’homme pour la documentation
Exemples
Sauter l’enquête pour les clients satisfaits
{
"type": "FlowControl",
"data": {
"condition": {
"type": "condition",
"fact": "questions/nps",
"operator": "gte",
"compare": { "value": 9 }
},
"action": {
"type": "survey-finish"
}
}
}
Afficher la page uniquement pour une tranche d’âge spécifique
{
"collections": {
"teen-questions": {
"name": "Questions pour les adolescents",
"condition": {
"type": "all",
"items": [
{
"type": "condition",
"fact": "questions/age",
"operator": "gte",
"compare": { "value": 13 }
},
{
"type": "condition",
"fact": "questions/age",
"operator": "lt",
"compare": { "value": 20 }
}
]
},
"elements": {
/* ... */
}
}
}
}
Conditions imbriquées complexes
{
"type": "any",
"name": "Utilisateurs Premium ou gros dépensiers",
"items": [
{
"type": "condition",
"fact": "questions/membership",
"operator": "eq",
"compare": { "value": "premium" }
},
{
"type": "all",
"items": [
{
"type": "condition",
"fact": "questions/total-spent",
"operator": "gt",
"compare": { "value": 1000 }
},
{
"type": "condition",
"fact": "questions/active-months",
"operator": "gte",
"compare": { "value": 6 }
}
]
}
]
}
Comparaison de deux faits
{
"type": "condition",
"fact": "questions/current-salary",
"operator": "gt",
"compare": { "fact": "questions/desired-salary" }
}
Utilisation de la propriété not
{
"type": "condition",
"fact": "questions/email-consent",
"operator": "true",
"not": true // Inverse le résultat : vrai lorsque email-consent n'est PAS vrai
}
Historique des Versions
| Version | Date | Changements |
|---|---|---|
| 1.0 | 15/11/2025 | Élément de paiement |
| 0.5 | 24/01/2025 | Première version publique |