Formato de Encuesta Abierto
Un formato abierto basado en JSON para definir encuestas y formularios. Utilizado por YourOpinion.is y de libre implementación para cualquiera.
Versión actual: 1.0 (Publicado: 15-11-2025)
Descargar Especificación
- Esquema JSON - Definición del formato legible por máquina
- Markdown - Documentación legible por humanos (optimizada para LLMs)
Introducción
El Formato de Encuesta Abierto proporciona una manera estandarizada de definir encuestas, cuestionarios y formularios como objetos JSON. Este formato permite:
- Portabilidad - Mover encuestas entre diferentes plataformas y herramientas.
- Control de versiones - Rastrear cambios en las encuestas usando herramientas
diffestándar. - Generación programática - Crear encuestas dinámicamente desde el código.
- Compatibilidad con LLM - Los asistentes de IA pueden crear y modificar encuestas fácilmente.
Conceptos Clave
Colecciones (Páginas)
Las encuestas se organizan en colecciones, que funcionan como páginas o secciones. Cada encuesta debe contener al menos una colección.
Elementos
Componentes individuales dentro de una colección, tales como:
- Preguntas (entrada de texto, opción múltiple, calificaciones, etc.)
- Bloques de contenido (texto markdown, imágenes)
- Elementos de control de flujo (lógica condicional, saltos de página)
Recursos
Componentes reutilizables que pueden ser referenciados por múltiples preguntas:
- Listas de opciones (para preguntas de selección)
- Escalas de calificación
- Recursos compartidos
Estructura del Documento
Una encuesta se representa como un objeto JSON con esta estructura:
{
"$schema": "https://youropinion.is/json-schema/1.0",
"$readme": "https://youropinion.is/docs/survey-format.md",
"collections": {
"collection-id-1": {
"name": "Nombre de la Colección",
"elements": {
"element-id-1": {
"type": "Markdown",
"data": {
/* Datos específicos del elemento */
}
}
},
"displayOrder": ["element-id-1"]
}
},
"displayOrder": ["collection-id-1"],
"assets": {
"asset-id-1": {
"type": "options",
"data": {
/* Datos específicos del recurso */
}
}
}
}
Propiedades de Nivel Superior
$schema (opcional)
URL a la definición del Esquema JSON para validación:
"$schema": "https://youropinion.is/json-schema/1.0"
$readme (opcional)
URL a la documentación legible por humanos:
"$readme": "https://youropinion.is/docs/survey-format.md"
collections (requerido)
Objeto que contiene las páginas/secciones de la encuesta. Cada clave es un ID de colección único:
"collections": {
"welcome": {
"name": "Página de Bienvenida",
"elements": { /* ... */ },
"displayOrder": ["intro", "consent"]
},
"questions": {
"name": "Preguntas Principales",
"elements": { /* ... */ },
"displayOrder": ["q1", "q2", "q3"]
}
}
Propiedades de la Colección:
name(cadena, opcional) - Nombre legible por humanos de la colección (no se muestra a los usuarios, se usa como referencia).condition(objeto, opcional) - Lógica condicional para determinar si esta colección debe mostrarse (ver sección Lógica Condicional).elements(objeto) - Contiene los elementos de esta colección. Cada clave es un ID de elemento único.displayOrder(array) - Array de IDs de elementos que define el orden de visualización.
Importante: El array displayOrder actúa tanto como filtro y secuenciador:
- Solo se mostrarán los elementos listados en
displayOrder. - Los elementos que no están en
displayOrderpermanecen en la definición pero están ocultos. - Incluir un ID de elemento inexistente causará un error.
displayOrder (requerido)
Array que especifica el orden de las colecciones:
"displayOrder": ["welcome", "questions", "thank-you"]
Se aplican las mismas reglas de filtrado: solo se mostrarán las colecciones listadas aquí.
assets (opcional)
Componentes reutilizables referenciados por múltiples elementos. Los recursos reducen la duplicación y facilitan el mantenimiento de las encuestas.
Tipos de Recursos:
options- Listas de opciones reutilizables para preguntasSelectOne/SelectMany.ordinal-scale- Escalas con etiquetas reutilizables para preguntasOrdinalScale.interval-scale- Escalas numéricas reutilizables para preguntasIntervalScale.
Ejemplo - Recurso de opciones:
"assets": {
"color-options": {
"type": "options",
"name": "Opciones de Color",
"data": {
"options": {
"red": { "label": "Rojo" },
"blue": { "label": "Azul" },
"green": { "label": "Verde" },
"yellow": { "label": "Amarillo" }
},
"displayOrder": ["red", "blue", "green", "yellow"]
}
},
"satisfaction-scale": {
"type": "ordinal-scale",
"name": "Escala de Satisfacción Estándar",
"data": {
"labels": {
"1": "Muy insatisfecho",
"2": "Insatisfecho",
"3": "Neutral",
"4": "Satisfecho",
"5": "Muy satisfecho"
}
}
},
"nps-scale": {
"type": "interval-scale",
"name": "Escala de Net Promoter Score",
"data": {
"start": 0,
"end": 10,
"labels": {
"start": "Poco probable",
"end": "Muy probable"
}
}
}
}
Todos los tipos de recursos requieren:
type- Tipo de recurso:"options","ordinal-scale", o"interval-scale".name- Nombre legible por humanos para fines de documentación.data- Estructura de datos específica del tipo.
Se puede hacer referencia a los recursos usando referencias JSON (ver sección Referencias JSON).
Tipos de Elementos
Los elementos son los bloques de construcción de tu encuesta. Cada elemento tiene una propiedad type y data. Todos los elementos pueden incluir opcionalmente un objeto extensions para metadatos personalizados (no utilizado por el renderizador estándar).
Tipos de elementos disponibles:
| Tipo | Categoría | Descripción |
|---|---|---|
Markdown | Contenido | Muestra texto y contenido formateado |
FlowControl | Control | Lógica condicional y navegación |
String | Pregunta | Entrada de texto (una o varias líneas) |
Number | Pregunta | Entrada numérica |
Date | Pregunta | Selector de fecha |
Boolean | Pregunta | Casilla de verificación Sí/No |
SelectOne | Pregunta | Selección única de opciones (botones de radio) |
SelectMany | Pregunta | Selección múltiple de opciones (casillas de verificación) |
IntervalScale | Pregunta | Escala de calificación numérica (ej. 0-10 para NPS, 1-5 para satisfacción) |
OrdinalScale | Pregunta | Escala de calificación con etiquetas (ej. Totalmente en desacuerdo a Totalmente de acuerdo) |
Payment | Pregunta | Elemento de procesamiento de pagos |
Elementos de Contenido
Markdown
Muestra texto formateado, encabezados, listas y otro contenido usando la sintaxis de Markdown.
{
"type": "Markdown",
"data": {
"markdown": "# ¡Bienvenido!\n\nGracias por participar en nuestra encuesta.\n\n- Por favor, responde con sinceridad\n- Todas las respuestas son anónimas"
}
}
Markdown Soportado:
- Encabezados (
#,##,###) - Listas (ordenadas y no ordenadas)
- Negrita (
**texto**) y cursiva (*texto*) - Enlaces (
[texto](url)) - Bloques de código
FlowControl
Controla el flujo de la encuesta con lógica condicional y navegación.
{
"type": "FlowControl",
"data": {
"condition": {
/* Opcional - Ver sección de Lógica Condicional */
},
"action": {
"type": "survey-finish" // Opciones: "survey-finish" o "page-finish"
}
}
}
Tipos de Acción:
survey-finish- Finalizar la encuesta inmediatamente.page-finish- Finalizar la página actual y pasar a la siguiente.
Para información detallada sobre la estructura de condiciones y ejemplos, consulta la sección Lógica Condicional más abajo.
Tipos de Preguntas
Todas las preguntas comparten estas propiedades comunes:
{
"type": "QuestionType",
"data": {
"label": "El texto de tu pregunta aquí",
"required": "yes", // Opcional: "yes", "no", o "suggested" (por defecto es "no")
"markdown": "Texto de ayuda" // Opcional: contexto adicional en Markdown
}
}
Propiedades comunes:
label(cadena, requerida) - El texto de la pregunta que se muestra a los usuarios.required(cadena, opcional) - Si la respuesta es obligatoria:"yes"(sí),"no"(no), o"suggested"(recomendada, se muestra como opcional pero se anima a responder).markdown(cadena, opcional) - Texto de ayuda adicional o descripción en formato Markdown.defaultValue(cualquiera, opcional) - Valor pre-rellenado para la pregunta.
String
Entrada de texto de una o varias líneas.
{
"type": "String",
"data": {
"label": "¿Cuál es tu nombre?",
"placeholder": "Introduce tu nombre completo", // Opcional
"multiline": false, // Opcional: true para un área de texto
"required": "yes"
}
}
Number
Entrada numérica con validación opcional.
{
"type": "Number",
"data": {
"label": "¿Cuántos empleados?",
"min": 1, // Opcional: valor mínimo
"max": 1000, // Opcional: valor máximo
"step": 1, // Opcional: tamaño del incremento (por defecto: 1)
"required": "yes"
}
}
Propiedades:
min(número, opcional) - Valor mínimo permitido.max(número, opcional) - Valor máximo permitido.step(número, opcional) - Tamaño del incremento para la validación de la entrada (por defecto: 1).
Date
Entrada de selector de fecha con nivel de precisión y restricciones de mínimo/máximo opcionales.
{
"type": "Date",
"data": {
"label": "¿Cuándo te uniste?",
"required": "suggested",
"accuracy": "day", // Opcional: "day", "month", o "year" (por defecto: "day")
"min": "2020-01-01", // Opcional: fecha más antigua seleccionable
"max": "2025-12-31" // Opcional: fecha más reciente seleccionable
}
}
Propiedades:
accuracy(cadena, opcional) - Nivel de precisión de la fecha:"day"- Selector de fecha completo con calendario (por defecto)."month"- Selección de mes y año en un menú desplegable."year"- Selección solo de año en un menú desplegable.
min(cadena, opcional) - Fecha más antigua seleccionable. Puede ser:- Cadena de fecha ISO (ej.,
"2020-01-01") - Cadena de tiempo relativo (ej.,
"+ 3 months","now","- 1 year")
- Cadena de fecha ISO (ej.,
max(cadena, opcional) - Fecha más reciente seleccionable. Mismas opciones de formato quemin.
Boolean
Casilla de verificación Sí/No. El valor por defecto es false (desmarcado).
{
"type": "Boolean",
"data": {
"label": "Términos y Condiciones",
"description": "Acepto los términos y condiciones" // Se muestra junto a la casilla de verificación
}
}
SelectOne
Pregunta de opción múltiple (botones de radio) - los usuarios seleccionan una opción.
{
"type": "SelectOne",
"data": {
"label": "¿Cuál es tu color favorito?",
"required": "yes",
"options": {
"options": {
"red": { "label": "Rojo" },
"blue": { "label": "Azul" },
"green": { "label": "Verde" }
},
"displayOrder": ["red", "blue", "green"]
}
}
}
Usando referencias a recursos:
{
"type": "SelectOne",
"data": {
"label": "Elige un color",
"options": { "$ref": "#/assets/color-options/data" }
}
}
SelectMany
Pregunta de opción múltiple (casillas de verificación) - los usuarios pueden seleccionar múltiples opciones.
{
"type": "SelectMany",
"data": {
"label": "¿Qué sistemas operativos usas?",
"required": "yes",
"options": {
"options": {
"windows": { "label": "Windows" },
"macos": { "label": "macOS" },
"linux": { "label": "Linux" }
},
"displayOrder": ["windows", "macos", "linux"]
},
"other": true, // Opcional: añade la opción "Otro" con campo de texto
"minSelections": 1, // Opcional: número mínimo de selecciones requeridas
"maxSelections": 3 // Opcional: número máximo de selecciones permitidas
}
}
IntervalScale
Escala de calificación numérica con un rango definido (ej., 0-10 para NPS, 1-5 para satisfacción). Comúnmente usada para:
- Net Promoter Score (NPS): escala de 0-10
- Calificaciones de satisfacción: escala de 1-5 o 1-7
- Preguntas de probabilidad: escala de 0-10
{
"type": "IntervalScale",
"data": {
"label": "¿Qué tan probable es que nos recomiendes a un amigo?",
"required": "yes",
"scale": {
"start": 0, // Número inicial de la escala
"end": 10, // Número final de la escala
"labels": {
// Etiquetas para los puntos de inicio y fin (requeridas)
"start": "Nada probable",
"end": "Extremadamente probable"
}
}
}
}
Casos de uso comunes:
// Net Promoter Score (NPS)
{
"type": "IntervalScale",
"data": {
"label": "¿Qué tan probable es que nos recomiendes?",
"scale": {
"start": 0,
"end": 10,
"labels": {
"start": "Poco probable",
"end": "Muy probable"
}
}
}
}
// Escala de satisfacción de 5 puntos
{
"type": "IntervalScale",
"data": {
"label": "¿Qué tan satisfecho estás con nuestro servicio?",
"scale": {
"start": 1,
"end": 5,
"labels": {
"start": "Muy insatisfecho",
"end": "Muy satisfecho"
}
}
}
}
Visualización: Muestra una escala horizontal con números clicables. Las etiquetas aparecen debajo de los puntos de inicio y fin.
OrdinalScale
Escala de calificación con etiquetas donde cada punto tiene una etiqueta personalizada. Ideal para:
- Escalas de Likert con redacción específica para cada punto.
- Escalas de acuerdo (Totalmente en desacuerdo → Totalmente de acuerdo).
- Escalas de frecuencia (Nunca → Siempre).
- Escalas de calificación personalizadas con etiquetas significativas.
{
"type": "OrdinalScale",
"data": {
"label": "¿Qué tan satisfecho estás con tu puesto?",
"required": "yes",
"scale": {
"labels": {
"1": "Muy insatisfecho",
"2": "Insatisfecho",
"3": "Neutral",
"4": "Satisfecho",
"5": "Muy satisfecho"
}
}
}
}
Casos de uso comunes:
// Escala de acuerdo de Likert
{
"type": "OrdinalScale",
"data": {
"label": "El producto cumplió mis expectativas.",
"scale": {
"labels": {
"1": "Totalmente en desacuerdo",
"2": "En desacuerdo",
"3": "Ni de acuerdo ni en desacuerdo",
"4": "De acuerdo",
"5": "Totalmente de acuerdo"
}
}
}
}
// Escala de frecuencia
{
"type": "OrdinalScale",
"data": {
"label": "¿Con qué frecuencia usas nuestro producto?",
"scale": {
"labels": {
"1": "Nunca",
"2": "Raramente",
"3": "A veces",
"4": "Frecuentemente",
"5": "Siempre"
}
}
}
}
Visualización: Muestra botones u opciones con etiquetas. Cada etiqueta se muestra completamente, haciendo que la escala sea autoexplicativa.
IntervalScale vs OrdinalScale:
- Usa IntervalScale cuando los números en sí mismos tienen significado (0-10, 1-5).
- Usa OrdinalScale cuando necesites etiquetas personalizadas para cada punto.
IntervalScalees más compacto;OrdinalScalees más descriptivo.
Payment
Recopila información de pago y procesa transacciones. Se integra con proveedores de pago configurados en los ajustes de tu encuesta.
{
"type": "Payment",
"data": {
"label": "Pago",
"required": "yes",
"amount": {
"value": 29.99,
"currency": "USD"
},
"captureMethod": "automatic" // Opcional: "immediate", "manual", o "automatic"
}
}
Propiedades:
amount(objeto, requerido) - Monto del pago convalue(número) ycurrency(código de 3 letras, ej., “USD”, “EUR”, “GBP”).captureMethod(cadena, opcional) - Cuándo capturar el pago:"immediate"- Capturar el pago inmediatamente cuando se envía la encuesta."manual"- Requiere captura manual a través de tu panel de pagos."automatic"- Capturar automáticamente cuando se completa la encuesta (por defecto).
Nota: El procesamiento de pagos requiere que un proveedor de pagos esté configurado en los ajustes de tu canal. Las monedas y métodos de pago soportados dependen de la configuración de tu proveedor.
Referencias JSON
Reduce la duplicación haciendo referencia a componentes reutilizables. Las referencias usan este formato:
{ "$ref": "[<ubicacion>]#<ruta>" }
ubicacion- URL al documento de origen (vacío = documento actual).ruta- Ruta desde la raíz del documento usando separadores/.
Ejemplo - Duplicación en línea:
{
"question-1": {
"type": "SelectOne",
"data": {
"label": "¿Color favorito?",
"options": {
"options": {
"red": { "label": "Rojo" },
"blue": { "label": "Azul" }
},
"displayOrder": ["red", "blue"]
}
}
},
"question-2": {
"type": "SelectOne",
"data": {
"label": "¿Color menos favorito?",
"options": {
"options": {
"red": { "label": "Rojo" },
"blue": { "label": "Azul" }
},
"displayOrder": ["red", "blue"]
}
}
}
}
Mejor - Usando recursos:
{
"collections": {
"main": {
"elements": {
"question-1": {
"type": "SelectOne",
"data": {
"label": "¿Color favorito?",
"options": { "$ref": "#/assets/colors/data" }
}
},
"question-2": {
"type": "SelectOne",
"data": {
"label": "¿Color menos favorito?",
"options": { "$ref": "#/assets/colors/data" }
}
}
},
"displayOrder": ["question-1", "question-2"]
}
},
"assets": {
"colors": {
"type": "options",
"data": {
"options": {
"red": { "label": "Rojo" },
"blue": { "label": "Azul" }
},
"displayOrder": ["red", "blue"]
}
}
}
}
Beneficios:
- Única fuente de verdad.
- Mantenimiento más fácil.
- Mejores
diffsen el control de versiones. - Tamaño de archivo más pequeño.
Lógica Condicional
La lógica condicional te permite crear encuestas dinámicas que se adaptan según las respuestas del usuario. Las condiciones se pueden usar de dos maneras:
1. Condiciones a Nivel de Colección
Muestra u oculta páginas enteras según las condiciones. Si la condición de una colección se evalúa como false, la página entera se omite y la ejecución pasa a la siguiente colección.
{
"collections": {
"follow-up": {
"name": "Preguntas de Seguimiento",
"condition": {
"type": "condition",
"fact": "questions/nps-score",
"operator": "lt",
"compare": { "value": 7 }
},
"elements": {
/* ... */
},
"displayOrder": ["question-1"]
}
}
}
En este ejemplo, la página “Preguntas de Seguimiento” solo se muestra si la puntuación de NPS es menor que 7.
2. Elementos FlowControl
Controla el flujo de la encuesta dentro de una página usando elementos FlowControl. Cuando la condición se evalúa como true, se ejecuta la acción especificada.
Acciones disponibles:
survey-finish- Finalizar la encuesta inmediatamente (omite todas las páginas restantes).page-finish- Finalizar la página actual y pasar a la siguiente (omite los elementos restantes en la página actual).
{
"type": "FlowControl",
"data": {
"condition": {
"type": "condition",
"fact": "satisfaction",
"operator": "eq",
"compare": { "value": "very-satisfied" }
},
"action": {
"type": "page-finish"
}
}
}
Nota: Si no se proporciona una condition, la acción siempre se ejecuta cuando se alcanza el elemento.
Estructura de la Condición
Las condiciones se definen como un árbol binario con dos tipos de nodos:
1. Condiciones de Comparación
Compara un dato (respuesta de la encuesta) con un valor u otro dato.
{
"type": "condition",
"fact": "questions/age",
"operator": "gt",
"compare": { "value": 18 }
}
Propiedades:
type- Siempre"condition"para comparaciones.fact(cadena) - La referencia al elemento en el formato ‘id-coleccion/id-elemento’ del cual leer el valor.operator(cadena) - Operador de comparación (ver operadores a continuación).compare(objeto, opcional) - Contra qué comparar:{ "value": <any> }- Comparar con un valor literal.{ "fact": "<id-coleccion/id-elemento>" }- Comparar con el valor de otro elemento.- No es necesario para operadores como
"exists"o"true".
not(booleano, opcional) - Invierte el resultado (por defecto:false).
Operadores soportados por tipo de elemento:
Number, IntervalScale, OrdinalScale, Date:
"eq"- Igual a"gt"- Mayor que"gte"- Mayor o igual que"lt"- Menor que"lte"- Menor o igual que"exists"- Tiene un valor (no necesitacompare)
String:
"eq"- Igual a"contains"- La cadena contiene el valor"exists"- Tiene un valor (no necesitacompare)
Boolean:
"true"- El valor es verdadero (no necesitacompare)"exists"- Tiene un valor (no necesitacompare)
SelectOne:
"eq"- Igual a una opción específica"in"- Es una de múltiples opciones (el valor decomparedebe tener formato deSelectMany)"exists"- Tiene un valor (no necesitacompare)
SelectMany:
"eq"- Coincide exactamente con un conjunto de opciones"exists"- Tiene al menos un valor (no necesitacompare)
2. Condiciones de Encadenamiento
Combina múltiples condiciones usando operadores lógicos.
{
"type": "all",
"items": [
{
"type": "condition",
"fact": "questions/age",
"operator": "gt",
"compare": { "value": 18 }
},
{
"type": "condition",
"fact": "questions/country",
"operator": "eq",
"compare": { "value": "US" }
}
]
}
Propiedades:
type- Operador lógico:"all"- Todas las condiciones deben ser verdaderas (lógica Y)."any"- Al menos una condición debe ser verdadera (lógica O).
items(array) - Array de condiciones (pueden ser comparaciones o cadenas anidadas).not(booleano, opcional) - Invierte el resultado de toda la cadena.name(cadena, opcional) - Etiqueta legible por humanos para documentación.
Ejemplos
Omitir encuesta para clientes satisfechos
{
"type": "FlowControl",
"data": {
"condition": {
"type": "condition",
"fact": "questions/nps",
"operator": "gte",
"compare": { "value": 9 }
},
"action": {
"type": "survey-finish"
}
}
}
Mostrar página solo para un rango de edad específico
{
"collections": {
"teen-questions": {
"name": "Preguntas para Adolescentes",
"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": {
/* ... */
}
}
}
}
Condiciones anidadas complejas
{
"type": "any",
"name": "Usuarios premium o que gastan mucho",
"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 }
}
]
}
]
}
Comparando dos datos
{
"type": "condition",
"fact": "questions/current-salary",
"operator": "gt",
"compare": { "fact": "questions/desired-salary" }
}
Usando la propiedad not
{
"type": "condition",
"fact": "questions/email-consent",
"operator": "true",
"not": true // Invierte el resultado: verdadero cuando email-consent NO es verdadero
}
Historial de Versiones
| Versión | Fecha | Cambios |
|---|---|---|
| 1.0 | 15-11-2025 | Elemento de pago |
| 0.5 | 24-01-2025 | Lanzamiento público inicial |