- Uso combinado de Google Forms, Sheets y Apps Script para gestionar reservas con control de plazas.
- Hojas auxiliares en Sheets para contar asistentes, calcular aforo y generar listados embebibles.
- Automatización con triggers y actualización dinámica de opciones, incluyendo cierre automático del formulario.
- Posibilidad de integrar un servidor de reservas REST con seguridad, idempotencia y manejo de errores de negocio.
Montar un sistema de reservas usando Google Forms y Sheets es una de las formas más rápidas y baratas de gestionar citas, plazas en eventos o listas de espera sin invertir en software caro. Con un formulario bien diseñado, una hoja de cálculo que haga los cálculos por ti y un poco de Google Apps Script, puedes tener un sistema bastante profesional funcionando en cuestión de horas.
En este artículo vamos a ver, con todo detalle, cómo combinar Google Forms, Google Sheets y Google Apps Script para crear un sistema de reservas con control de aforo, actualización automática de plazas, listado de asistentes embebible en tu web y, si lo necesitas, integración con un servidor de reservas externo por API siguiendo el enfoque que usa Google Actions Center. La idea es que termines con una base sólida que puedas adaptar a tu negocio: desde un pequeño curso hasta un sistema de citas más avanzado.
Planteamiento del sistema de reservas con Google Forms y Sheets
La base de todo el flujo es un formulario de registro sencillo donde el usuario introduce sus datos y elige la sesión o recurso que quiere reservar. Cada envío del formulario se guarda automáticamente en una hoja de cálculo de Google Sheets, donde calculamos cuántas plazas hay ocupadas, cuántas quedan y quién está apuntado a cada sesión.
Google Forms, por sí solo, no permite bloquear plazas ni ocultar opciones agotadas, así que aquí entra en juego Google Apps Script. Con un script asociado al formulario o a la hoja de cálculo, se puede actualizar de forma dinámica el texto de las opciones (por ejemplo, añadiendo “(25 plazas restantes)”) o incluso eliminar de la lista aquellas sesiones que ya están completas.
Cuando todas las sesiones están llenas, el script también puede cerrar automáticamente el formulario para que nadie más pueda enviar solicitudes. Todo este proceso se coordina con los datos de la hoja “de control” que prepara Google Sheets, donde se hace el recuento de asistentes y se calcula el aforo restante en cada caso.
Además, si quieres un sistema más avanzado o ya trabajas con un backend propio, puedes implementar un servidor de reservas mediante API REST que reciba las peticiones de Google (por ejemplo, desde Actions Center), cree o actualice reservas en tu sistema y devuelva estados, errores y datos normalizados, garantizando idempotencia y autenticación segura.
Diseñar el formulario de reservas en Google Forms
El primer paso es crear un formulario minimalista pero bien pensado. Lo normal es incluir al menos el nombre de la persona que reserva y la sesión o actividad que quiere reservar. Puedes añadir más preguntas (correo, teléfono, comentarios, etc.), pero conviene empezar con lo básico para centrarte en la lógica de las plazas.
En Google Drive, crea un nuevo formulario y asigna un título claro. Añade una pregunta de tipo respuesta corta para el nombre y otra de tipo “Elección múltiple” para las sesiones disponibles. Cada opción de la elección múltiple representará una sesión o recurso a reservar.
Cuando añades preguntas de texto corto, verdadero/falso o elección múltiple, Google Forms te pide un título y unas opciones; en el mundo de Google Apps Script, todo esto se considera un “item” del formulario. Es importante tener presente este concepto porque luego, al programar, necesitaremos localizar el item concreto que lista las sesiones.
Imagina que propones cuatro seminarios. Podrías definir las opciones inicialmente con un texto que incluya el horario y la capacidad total, por ejemplo: “Seminario 1: 10:00-12:00 (100 plazas restantes)”. Esta será la información que verá el primer usuario que abra el formulario, y el script se encargará de ir reduciendo el número de plazas en ese texto.
Si quieres, podrías integrar este bloque de reservas como parte de un formulario más extenso (por ejemplo, una encuesta previa y al final el bloque de reserva), pero para entender bien la lógica es más cómodo trabajar con un formulario simple centrado únicamente en la reserva de plazas.
Conectar Google Forms con Google Sheets
Para que el sistema funcione, necesitas que cada envío del formulario acabe en una hoja de cálculo vinculada. Desde la pestaña “Respuestas” de Google Forms verás un icono con el típico logotipo verde de Sheets; al pulsarlo, el asistente te permitirá crear una hoja nueva o vincular el formulario a una hoja existente.
Lo más cómodo al principio es crear una hoja nueva. En esa hoja verás una pestaña llamada algo como “Form responses 1” donde irán apareciendo todas las filas con los datos que la gente envía: marca de tiempo, nombre del registrante y seminario elegido, junto con cualquier otro campo que hayas añadido.
Antes de seguir con fórmulas o scripts, resulta muy útil enviar unos cuantos envíos de prueba desde el propio formulario (usando el botón de vista previa). De esta manera te aseguras de que la estructura de columnas es la que esperas y puedes ajustar fórmulas sin miedo a equivocarte.
No olvides comprobar que el formulario está en modo “Aceptando respuestas”; de lo contrario, ni tú ni tus usuarios podréis hacer envíos de prueba y pensarás que algo se ha roto cuando en realidad solo faltaba activar esa opción.
Crear un listado legible de asistentes por sesión
Trabajar solo con la pestaña de respuestas no es muy cómodo si quieres tener una visión clara de quién va a cada sesión. Por eso, un buen truco es crear una pestaña auxiliar donde se muestre, de forma ordenada, un listado de asistentes por seminario que luego podrás incluso incrustar en tu web.
Crea una nueva hoja dentro del mismo documento de Sheets y llámala, por ejemplo, “Registerees” o “Asistentes”. Utiliza las primeras filas para poner un título bonito y algún texto introductorio, pero lo importante empezará unas filas más abajo con los encabezados.
En la fila de cabecera de tiempos, puedes definir columnas como “Hora”, “10:00-12:00”, “12:00-14:00”, etc. Debajo, en otra fila, pon los nombres exactos de los seminarios tal y como aparecen en el formulario, pero sin el texto de “plazas restantes”. Esta coincidencia de texto será clave para localizar a quién corresponde cada reserva.
En la primera columna (A), desde una fila inferior hacia abajo, numera las filas con 1, 2, 3… hasta tu capacidad máxima. Estas filas representarán las posibles plazas de cada seminario, de modo que cada celda horizontalmente contendrá el nombre de una persona que se ha apuntado a esa sesión.
La clave para rellenar estos nombres de forma automática está en combinar varias funciones de Sheets: FILTER, REGEXMATCH, UNIQUE e IFERROR. Empezamos con FILTER, que permite mostrar solo aquellas filas que cumplan una condición basada en otra columna, por ejemplo “mostrar solo los nombres cuyo seminario coincide con el encabezado de esta columna”.
Sin embargo, en tu formulario el texto de la opción de seminario incluirá el número de plazas restantes, que se va actualizando, por lo que jamás coincidirá exactamente con el texto estático de tu encabezado. Para resolver esto se recurre a REGEXMATCH, que permite comprobar si una celda contiene un texto determinado en cualquier parte del contenido, aunque haya otros caracteres alrededor.
El patrón típico sería algo así como: REGEXMATCH(columna_del_seminario, encabezado). Si REGEXMATCH devuelve TRUE, significa que el seminario seleccionado en esa respuesta incluye el texto del encabezado, y FILTER se queda con esa fila. De este modo, aunque en la respuesta aparezca “Seminario X (85 plazas restantes)”, al buscar por “Seminario X” la coincidencia será válida.
Existe otro problema habitual: algunas personas pueden intentar apuntarse dos veces al mismo seminario (por despiste o con mala idea). Para evitar que aparezcan duplicados en el listado de asistentes, se envuelve la función FILTER con UNIQUE, de manera que solo se muestra una vez cada nombre que cumpla la condición.
Por último, si nadie se ha apuntado todavía a un seminario concreto, FILTER suele lanzar un error de tipo #N/A. Para no tener ese mensaje tan feo en una hoja que vas a incrustar en tu web, se usa IFERROR alrededor de toda la fórmula, de manera que el error se oculta y la celda se queda vacía cuando aún no hay registrados.
Calcular cuántas plazas hay ocupadas y cuántas quedan
Una vez tienes la lista de asistentes más o menos legible, toca crear la hoja de control de aforo, que es la que utilizará el script para saber si queda sitio en cada sesión y cuánto debe mostrar en el texto de las opciones del formulario.
Crea otra pestaña en el mismo documento de Sheets y ponle un nombre claro, como “Count” o “Aforo”. En la columna A vas a listar todos los seminarios exactamente con el mismo nombre que en el formulario, pero esta vez puedes incluir también los horarios si te resulta cómodo.
En otra parte de la hoja (por ejemplo, una celda destacada en la parte superior derecha) define un valor que represente la capacidad máxima de cada sesión (por ejemplo, 100 plazas). Esta referencia será la que uses para calcular cuántas plazas quedan restando las reservas confirmadas.
En la columna B de la hoja de control define una fórmula que, básicamente, hace lo mismo que la fórmula de asistentes, pero envuelta en COUNTA para contar cuántos registros hay. Al combinar COUNTA con FILTER, REGEXMATCH, UNIQUE e IFERROR, obtienes el total de personas únicas apuntadas a cada seminario sin duplicados y sin errores de #N/A.
En la columna C, la lógica es simple: restar la cantidad de asistentes (columna B) a la capacidad máxima (la celda que definiste para el aforo). Esto te devuelve, para cada fila de la columna A (cada seminario), un número con las plazas restantes. Esta matriz será la que lea tu script para decidir qué opciones mostrar y con qué texto.
Esta hoja de control se actualiza automáticamente cada vez que se recibe una nueva respuesta en la pestaña de formularios. No necesitas tocar nada a mano: las fórmulas harán el trabajo de recuento por ti en segundo plano mientras el sistema sigue aceptando reservas.

Automatizar el formulario con Google Apps Script
El componente que convierte este montaje en un auténtico sistema de reservas dinámico es Google Apps Script. Desde el editor de scripts, asociado al formulario o a la hoja de cálculo, se puede programar la actualización de las opciones y el cierre del formulario cuando el aforo llega a cero.
Para abrir el editor, en el formulario ve al menú de los tres puntos verticales y selecciona “Editor de secuencias de comandos”. Desde la hoja de cálculo, lo encontrarás en “Herramientas > Editor de secuencias de comandos”. En ambos casos se abre el mismo proyecto de Apps Script vinculado al documento.
La idea es crear una función principal que se dispare cada vez que se envía una respuesta, algo así como onFormSubmit(). Esa función tendrá que leer la matriz de datos de la pestaña de control (“Count”), filtrar los seminarios con plazas, actualizar el texto de las opciones del formulario y, si no queda ninguna, desactivar la aceptación de respuestas.
Al principio del script conviene declarar una serie de variables globales: la capacidad máxima de plazas, el ID del formulario, el ID del item de sesiones, el ID de la hoja de cálculo, el nombre de la pestaña con los datos de aforo y el rango concreto de celdas que contienen nombre del seminario, plazas ocupadas y plazas restantes.
Para obtener el ID del item de sesiones (la pregunta de tipo elección múltiple), se puede escribir una pequeña función de ayuda que recorra los items del formulario, imprima en el registro de logs sus títulos y sus IDs, y así localizar el valor correcto. Una vez localizado, se copia ese número y se usa en la variable global correspondiente.
Hay un detalle práctico importante: cuando se envía un formulario, Google necesita un pequeño margen para volcar la respuesta en la hoja. Por eso muchos desarrolladores incluyen una función “sleep” artesanal que espera unos pocos cientos o miles de milisegundos antes de empezar a leer los datos de la hoja, asegurándose de que la nueva fila ya está disponible.
Dentro de onFormSubmit(), el flujo típico será: abrir la hoja por ID, abrir la pestaña de control por nombre, leer el rango de datos de los seminarios y guardar el resultado en un array bidimensional de JavaScript. A continuación, abrir el formulario por ID y acceder al item de sesiones usando el ID que hemos descubierto antes.
Con la matriz de datos cargada, se aplica un filtro en JavaScript para quedarse únicamente con las filas donde el número de plazas restantes sea mayor que cero. Ese conjunto será la lista de sesiones que siguen disponibles. Si el resultado del filtro es un array vacío, significa que todas las sesiones están completas.
En el caso de que no haya plazas libres, el script puede cerrar el formulario con FormApp.setAcceptingResponses(false) y definir un texto personalizado informando de que el periodo de reservas ha terminado. Desde el punto de vista del usuario, el formulario aparecerá como “cerrado” con tu mensaje de aviso.
Si todavía quedan sesiones con aforo, el script recorre esas filas filtradas y construye un array de strings que combine el nombre de la sesión con el número de plazas disponibles, por ejemplo: “Seminario X – 32 plazas restantes”. Ese array se pasa luego a setChoiceValues del multipleChoiceItem para que el formulario se actualice instantáneamente.
Por último, para que la función onFormSubmit() se ejecute siempre que haya un envío, se configura un trigger desde el menú “Editar > Desencadenadores del proyecto actual” en el editor de Apps Script. Allí se elige la función, el origen del evento (desde formulario) y el tipo de evento (al enviar el formulario). De este modo, tu lógica se dispara de forma automática cada vez que un usuario realiza una reserva.
Incrustar el formulario y la lista de asistentes en tu web
Una vez que el sistema funciona, lo ideal es integrarlo en tu página web o intranet para que los usuarios no tengan que salir de tu sitio para reservar. Google Forms y Google Sheets facilitan bastante esta parte mediante código de inserción (iframe).
Para incrustar el formulario, desde la pantalla de edición pulsa en “Enviar” y selecciona el icono de insertar (“<>”). El cuadro de diálogo te mostrará un fragmento de iframe con la URL del formulario, además de campos para ajustar el ancho y el alto. Copia ese código y pégalo en el HTML de tu página donde quieras mostrar el formulario.
En el caso de la hoja de asistentes, probablemente solo querrás mostrar la pestaña donde tienes la lista ordenada por seminarios. Para ello, desde Sheets ve a “Archivo > Publicar en la web”, selecciona la opción “Insertar”, elige la pestaña correcta y confirma la publicación. Google generará otro iframe que podrás pegar en tu web.
Es posible que necesites retocar manualmente el ancho y la altura del iframe para que se vea bien dentro del diseño de tu página (por ejemplo, ancho al 100% y una altura generosa para evitar scroll excesivo). Aunque no es obligatorio, queda más limpio si incrustas el listado de asistentes en una sección aparte de la página, diferenciada visualmente del formulario de reserva. También puedes sincronizar las reservas con Google Calendar para notificaciones y recordatorios.
En algunos proyectos, se combina esta incrustación con estilos CSS personalizados para que tanto el formulario como la hoja incrustada se integren mejor con la imagen corporativa del sitio, aunque el contenido siga alojado en Google.
Implementar un servidor de reservas mediante API REST
Más allá del uso puramente interno de Forms y Sheets, Google ofrece la posibilidad de integrar tus reservas con Actions Center u otros sistemas externos a través de un servidor de reservas propio que exponga una API REST. Esta aproximación es ideal si ya dispones de un backend o quieres una arquitectura más escalable.
La idea es que Google actúe como interfaz hacia el usuario (en móvil, web u otros canales) y, cuando el usuario solicite una reserva, Google llame a tu servidor de reservas para crear o actualizar la cita en tiempo real. Existen dos variantes principales: la implementación estándar (citas/reservas normales) y la implementación de listas de espera, destinada a un programa piloto específico.
En la implementación estándar se trabaja con dos recursos clave: el “Espacio” (Slot o recurso del inventario: una mesa, un horario, un servicio) y la “Reserva” (la cita concreta sobre ese espacio). Tu servidor expone métodos como CreateBooking y UpdateBooking, entre otros, para que Google pueda gestionar el ciclo de vida de las reservas en tu nombre.
Cuando un usuario crea una reserva desde la interfaz de Google, la plataforma te envía datos como nombre, apellidos, teléfono y correo electrónico. Desde el punto de vista de tu sistema, se trata de una compra o reserva como invitado, ya que Actions Center no tiene acceso a las cuentas internas de tu plataforma, y tú tampoco debes asumir que ese usuario ya existe en tu base de datos.
Tu obligación es que la reserva que registre tu backend sea coherente con el resto de reservas que se generan por tus propios canales (web, app, teléfono, etc.). Si tus reservas internas generan correos de confirmación, números de localizador o estados concretos, la reserva creada a través de Google debería seguir exactamente la misma lógica para evitar inconsistencias.
Antes de pasar a producción, es imprescindible levantar un servidor de pruebas o sandbox que se conecte al entorno de pruebas de Actions Center. Solo cuando hayas verificado que todos los métodos responden correctamente (incluidas las situaciones de error) deberías configurar el endpoint de producción y exponerlo a usuarios reales.
Google publica definiciones de servicio en formato proto que puedes descargar para acelerar la implementación de la API, tanto en Node.js como en Java u otros lenguajes compatibles. También existen ejemplos de esquemas de servidor que simulan los métodos REST necesarios para que puedas usarlos como plantilla.
Resumiendo todo lo anterior, puedes montar con herramientas gratuitas de Google un sistema de reservas sorprendentemente potente: un formulario que muestra solo las sesiones con plazas, una hoja de cálculo que cuenta asistentes y calcula aforo restante, un script que actualiza las opciones y cierra el formulario cuando se llena todo, y, si lo necesitas, un servidor de reservas REST que hable con Google Actions Center de forma segura, idempotente y con manejo fino de errores, acercándote bastante a lo que ofrecen muchas plataformas comerciales especializadas.
Redactor especializado en temas de tecnología e internet con más de diez años de experiencia en diferentes medios digitales. He trabajado como editor y creador de contenidos para empresas de comercio electrónico, comunicación, marketing online y publicidad. También he escrito en webs de economía, finanzas y otros sectores. Mi trabajo es también mi pasión. Ahora, a través de mis artículos en Tecnobits, intento explorar todas las novedades y nuevas oportunidades que el mundo de la tecnología nos ofrece día a día para mejorar nuestras vidas.

