Embeber un widget de chat sobre la base de conocimiento con lead capture
Guía práctica para embeber Simmetric Chat en tu sitio: loader en iframe sandboxeado, model pin resuelto del lado del servidor, lead capture y configuración de CORS.
Convierte tu documentación en un asistente en la puerta
Tu base de conocimiento ya contiene las respuestas que buscan tus visitantes. Un widget de chat embebido lleva esas respuestas a tu sitio web como puerta de entrada conversacional: los visitantes hacen preguntas, el widget ejecuta el mismo pipeline RAG híbrido y la misma infraestructura de agente que usan tus equipos internos, y las respuestas llegan con citas de los workspaces que decidas exponer. Este tutorial recorre el embed del widget, el control sobre lo que responde, la captura de leads y la correcta configuración de CORS - del panel de administración a un snippet funcionando en unos minutos.
El embed en dos pasos: un loader y un iframe sandboxeado
El widget está construido en torno a un patrón de embed orientado a la seguridad. En lugar de inyectar markup y estilos en tu página, el widget llega en dos pasos:
- El script loader. Añade una sola etiqueta script al sitio, apuntada a tu servicio widget con el ID del widget. El loader es un pequeño archivo JavaScript que crea un iframe en la página anfitriona.
- El panel iframe. El iframe carga una aplicación Preact autónoma - compilada como bundle IIFE con CSS inline - que dibuja el botón flotante, el panel de chat y cada interacción dentro de su propio documento.
<script src="https://tu-simmetric-chat.com/widget/loader.js?widgetId=WIDGET_ID"></script>¿Por qué un iframe? Porque interpolar cadenas de contenido no confiable en una página anfitriona es la vía clásica del XSS. Hacer correr la interfaz del widget dentro de un iframe sandboxeado de origen opaco elimina por completo esa clase de riesgo: el contenido del chat nunca se ejecuta en el contexto de tu página. Las antiguas rutas de embed por interpolación de cadenas se retiraron del producto exactamente por esta razón, así que el patrón en dos pasos no es una opción entre varias - es el embed.
La comunicación entre iframe y página pasa por un pequeño protocolo postMessage versionado (tipos de mensaje simmetric:*) que gestiona el ballet de apertura/cierre del FAB, el recoloreado del FAB y los handshakes del storage de sesión. Ambos lados validan cada mensaje entrante contra el exacto contentWindow esperado, de modo que los mensajes falsificados entre iframes distintos se ignoran.
Crear el widget y apuntarlo al conocimiento
Todo empieza en el panel de administración:
- Crea un widget desde Ajustes → Widgets. La creación está atada a la licencia (
widget_enabled) y respeta el límite numérico de widgets del plan. - Vincula el widget a uno o varios workspaces. La whitelist de workspaces reemplaza atómicamente todos los vínculos previos, así que estratificar el acceso a la base de conocimiento es cuestión de qué workspaces adjuntar.
- Configura el branding: color primario, nombre del bot, logos, posición (abajo a la derecha o abajo a la izquierda). Los despliegues de nivel Community reciben valores por defecto sensatos cuando los campos están vacíos; la personalización completa y el white-labeling son flags enterprise.
- Copia el snippet de embed en el HTML de tu sitio.
Como los widgets se definen por workspace, el conocimiento del que un widget puede extraer es exactamente la unión de las bases de conocimiento de los workspaces vinculados - nada más. Un widget de soporte puede ver el workspace de la documentación pública sin tocar jamás los datos de proyectos internos.
El model pin de las respuestas: resuelto del lado del servidor
Una adición reciente cuenta para el control de calidad: la configuración de cada widget puede seleccionar un provider y un modelo LLM específicos que sirven las respuestas de chat de ese widget. El pin se conserva en la fila del widget y se resuelve del lado del servidor en cada petición de chat - nunca lo proporciona el cliente, el proxy del widget ni el navegador del visitante. Un modelo fijado tiene prioridad sobre el default del workspace, y los widgets sin pin mantienen la cadena de resolución estándar. En la práctica: tu widget de marketing puede correr sobre el exacto modelo que verificaste para respuestas públicas, independientemente de lo que cualquiera manipule del lado del cliente.
Una captura de leads que respeta a los visitantes
La captura de leads del widget está diseñada para la realidad de un formulario público: los abusos se concentran donde se recogen datos, así que el endpoint de leads está voluntariamente limitado a 3 peticiones por hora por fuente (con el límite visible para el usuario). El flujo:
- El visitante ve una barrera de consentimiento sobre información personal antes de chatear - un reconocimiento explícito de cómo se tratan los datos, no un enlace a una política escondido al final.
- Una tarjeta lead recoge los datos de contacto durante o después de la conversación, y los envíos llegan al buzón de leads del widget en el panel de administración, con exportación CSV para tu pipeline.
- Las sesiones son anónimas por decisión de diseño: el servidor crea una sesión con un token de 256 bits y una caducidad de 24 horas, y cada petición posterior se valida contra ella. Los límites por sesión (20 mensajes por hora, 5 conversaciones al día) devuelven un
429con una indicaciónretryAfteral superarse, y la interfaz muestra un aviso de rate limit en lugar de fallar en silencio.
Los rate limits forman parte de la historia de confianza, no un añadido posterior: una superficie de chat pública debería degradar con gracia bajo carga o abuso, y el limiter de leads es la barrera más estricta de los tres limiters del lado del widget.
CORS: cerrado por defecto por diseño
El tráfico de widgets cruza orígenes por definición, así que CORS forma parte de la superficie de seguridad en lugar de ser un añadido posterior. Cada widget lleva su propia lista allowedOrigins, editable desde el panel de administración. En tiempo de ejecución, un middleware CORS dinámico valida la cabecera Origin de cada petición contra la lista de ese widget - las peticiones de orígenes no permitidos se rechazan en el preflight, y el middleware falla en modo cerrado: si la comprobación de origen no puede consultar la base de datos, el acceso se deniega en lugar de concederse.
Configúralo en una sola pasada:
- Añade los orígenes de tu sitio (esquema y host, sin juegos con la barra final) a los orígenes permitidos del widget.
- Recuerda que las variantes de subdominio cuentan como orígenes distintos -
ejemplo.comywww.ejemplo.comson dos entradas. - Usa orígenes
https://en producción; el servicio widget habla las mismas reglas de URL que el resto de la stack.
Todo lo demás - la URL del loader, el iframe, el bootstrap de la sesión, el stream SSE del chat - usa el mismo host en el que despliegas el servicio widget, así que hay exactamente un lugar donde se decide la confianza de origen: la lista permitida del widget.
Qué corre dónde
Un mapa de orientación rápido, porque el widget toca tres procesos:
- Servidor principal - CRUD y branding de widgets, vinculación de workspaces, la API interna que el servicio widget llama con su clave API, y endpoints lead/analytics para administradores. Todo el router interno devuelve
402cuando la funcionalidad widget está apagada. - Servicio widget - la superficie pública de embed: loader JS, HTML del iframe, creación de sesiones, entrega de la configuración en caché, el proxy SSE del chat hacia el servidor principal y el endpoint de leads. Se autentica ante el servidor principal con una
WIDGET_API_KEYy lleva sus propios limitadores de frecuencia. - El iframe - el cliente Preact IIFE con el ciclo de vida del chat: creación de la sesión, streaming SSE token a token, visualización de citas, preguntas sugeridas y barreras de consentimiento.
El proxy del chat reenvía el mismo formato de eventos de la API de streaming interna - mensajes de estado, anuncios de plan, tokens en streaming, citas y eventos terminales done/error - para que todo lo que tu equipo ve en un chat de workspace, tus visitantes lo experimenten en el widget.
Checklist de lanzamiento
- Widget creado, funcionalidad de licencia activa, workspaces vinculados
- Branding configurado; flag white-label si el widget no debe llevar la marca del producto
- Model pin de respuestas definido en la fila del widget (resuelto del lado del servidor)
- Orígenes permitidos que cubren cada sitio y subdominio que lo embederá
- Lead capture verificado de punta a punta: barrera de consentimiento, envío, buzón admin, exportación CSV
- Rate limits comprendidos: 3 leads por hora, 20 mensajes por hora por sesión, 5 conversaciones al día
A partir de ahí, el widget es un drop-in: una etiqueta script, una lista permitida, una base de conocimiento en la que ya confías. Cuando tus visitantes hacen preguntas, obtienen respuestas fundadas exactamente en los workspaces que elegiste - con un pipeline de lead capture que es cortés con los humanos y severo con los bots.

