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 diff está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 displayOrder permanecen 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:

  1. options - Listas de opciones reutilizables para preguntas SelectOne/SelectMany.
  2. ordinal-scale - Escalas con etiquetas reutilizables para preguntas OrdinalScale.
  3. interval-scale - Escalas numéricas reutilizables para preguntas IntervalScale.

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:

TipoCategoríaDescripción
MarkdownContenidoMuestra texto y contenido formateado
FlowControlControlLógica condicional y navegación
StringPreguntaEntrada de texto (una o varias líneas)
NumberPreguntaEntrada numérica
DatePreguntaSelector de fecha
BooleanPreguntaCasilla de verificación Sí/No
SelectOnePreguntaSelección única de opciones (botones de radio)
SelectManyPreguntaSelección múltiple de opciones (casillas de verificación)
IntervalScalePreguntaEscala de calificación numérica (ej. 0-10 para NPS, 1-5 para satisfacción)
OrdinalScalePreguntaEscala de calificación con etiquetas (ej. Totalmente en desacuerdo a Totalmente de acuerdo)
PaymentPreguntaElemento 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")
  • max (cadena, opcional) - Fecha más reciente seleccionable. Mismas opciones de formato que min.

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.
  • IntervalScale es más compacto; OrdinalScale es 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 con value (número) y currency (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 diffs en 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 necesita compare)

String:

  • "eq" - Igual a
  • "contains" - La cadena contiene el valor
  • "exists" - Tiene un valor (no necesita compare)

Boolean:

  • "true" - El valor es verdadero (no necesita compare)
  • "exists" - Tiene un valor (no necesita compare)

SelectOne:

  • "eq" - Igual a una opción específica
  • "in" - Es una de múltiples opciones (el valor de compare debe tener formato de SelectMany)
  • "exists" - Tiene un valor (no necesita compare)

SelectMany:

  • "eq" - Coincide exactamente con un conjunto de opciones
  • "exists" - Tiene al menos un valor (no necesita compare)

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ónFechaCambios
1.015-11-2025Elemento de pago
0.524-01-2025Lanzamiento público inicial