Tema
Widget embebible
El camino más corto para tener un agente en tu web: una etiqueta <script> y ya hay un chat flotante, con los colores que hayas configurado en el panel.
Por debajo es un Web Component (<ur-agent-chat>) sin dependencias de framework, que delega toda la comunicación en @nykk/ur-agent-client.
Antes de empezar
El canal del widget tiene que estar habilitado, y tu dominio permitido en su lista de orígenes. En el panel lo tienes en la ficha del agente, sección Canales, fila «Chat embebible en cualquier web» (@nykk/ur-agent-widget) — internamente es el canal widget. Ver Canales.
El snippet
html
<script
src="https://<tu-backend-ur>/widget.js"
data-agent="<id-del-agente>"
></script>Eso es todo. El script se inyecta solo en document.body y se descarga del backend el título y los colores del agente, así que normalmente no hace falta nada más.
El panel te da este mismo snippet ya relleno, en esa misma ficha («Chat embebible»), con el id del agente y no con su identifier. Usa ese: el identifier es un slug derivado del nombre y se regenera al renombrar el agente, con lo que el embed dejaría de encontrarlo.
Sirve /widget.js desde tu backend de ur
El bundle lo publica el propio backend, y así el widget siempre va en la misma versión que la API con la que habla. Además, por defecto resuelve a qué backend llamar a partir del origen desde el que se ha descargado: si lo copias a otro dominio o a un CDN tendrás que añadir data-api-base con el origen de tu backend — y acordarte de actualizar la copia en cada versión.
Atributos del <script>
| Atributo | Por defecto | Qué hace |
|---|---|---|
data-agent | — | Obligatorio. El id (UUID) del agente, tal y como lo rellena el panel. También se acepta su identifier, pero cambia si renombras el agente |
data-api-base | El origen del script | Backend de ur, si es otro |
data-channel | widget | El canal por el que entra |
data-title | Del panel, o Asistente virtual | Título de la cabecera |
data-color | Del panel | Color principal (cabecera, burbuja del usuario) |
data-color-text | Del panel | Color del texto sobre el color principal |
data-color-bot | Del panel | Fondo de las burbujas del agente |
data-context | — | Contexto de cliente, como JSON |
data-lang | Los idiomas del navegador | El idioma del mensaje automático (eu, es-MX): ponlo si tu web deja elegir idioma. No cambia los textos del widget (abajo) |
Como módulo, dentro de tu app
Si ya tienes un bundler y prefieres colocar el elemento tú:
bash
npm install @nykk/ur-agent-widgetts
import '@nykk/ur-agent-widget';html
<ur-agent-chat
agent="<id-del-agente>"
api-base="https://<tu-backend-ur>"
title="Asistente virtual"
></ur-agent-chat>Importado así no se auto-monta nada: el elemento se crea donde tú lo pongas en el DOM. Eso sí, por defecto se sigue pintando como burbuja flotante fija abajo a la derecha, esté donde esté; si lo que quieres es que ocupe su contenedor, añade el atributo inline. Además de los atributos, tiene dos propiedades de JavaScript: context (abajo) y getUserToken (Usuario identificado). Los atributos son los mismos de la tabla de arriba sin el prefijo data-, más tres que solo existen en esta forma. El de idioma es el lang estándar del propio elemento (<ur-agent-chat lang="eu">), no el que hereda de <html>; se lee al arrancar, así que para cambiarlo después hay que volver a montar el elemento.
| Atributo | Qué hace |
|---|---|
subject | Reanuda una conversación concreta en vez de la guardada en el navegador (hasta 256 caracteres). Quien conozca el valor puede leer esa conversación y seguirla, así que no pongas algo que se pueda adivinar (el id o el email de tu usuario) |
started-at | Fecha ISO. Cambia la cabecera: en vez del título muestra la fecha y el canal de esa conversación, y oculta el enlace de reinicio. Pensado para revisar un hilo existente — no deshabilita el envío: quien lo tenga delante puede seguir escribiendo |
inline | Booleano. En vez de flotar, rellena su contenedor y arranca ya desplegado; oculta la burbuja, el botón de minimizar, el de maximizar y el enlace de reinicio |
Colores y tema
Al arrancar, el widget pide al backend la Apariencia de su canal («Chat embebible», widget) y rellena con ella el título y los colores que no le hayas fijado explícitamente. Es decir: el sitio de cambiar la marca es el panel, y el snippet se queda limpio. Cada canal tiene la suya: lo que pongas en «Integración a medida» es para los clientes del SDK y no le afecta al widget.
Para un control más fino, el componente expone variables CSS en su :host:
css
ur-agent-chat {
--uw-primary: #4f46e5;
--uw-primary-text: #ffffff;
--uw-bot-bubble: #f1f5f9;
--uw-radius: 12px;
--uw-panel-width: 380px;
--uw-panel-height: 600px;
--uw-bottom: 24px;
--uw-right: 24px;
}Están además --uw-primary-hover, --uw-bg, --uw-text, --uw-text-secondary, --uw-user-bubble, --uw-user-text, --uw-bot-text, --uw-border, --uw-input-bg, --uw-font, --uw-shadow y --uw-bubble-size.
Contexto por turno
Si las tools del agente declaran contexto, puedes pasárselo. Desde HTML:
html
<script
src="https://<tu-backend-ur>/widget.js"
data-agent="soporte"
data-context='{"visitor_context":{"page":"/precios"}}'
></script>Desde JavaScript es mejor asignar la propiedad — evita el parseo y permite actualizarla conforme el usuario navega, sin recrear el widget (que perdería la conversación):
js
document.querySelector('ur-agent-chat').context = {
visitor_context: { page: '/contacto' },
};Un JSON mal formado en el atributo no rompe el widget: se avisa por consola y se ignora.
Lee Contexto de cliente antes de usarlo — sobre todo la parte de que no es una credencial.
Usuario identificado
Si el agente identifica a su usuario, el widget necesita el token de quien usa tu web: un JWT que firma tu backend. Se lo das con la propiedad getUserToken, una función que lo devuelve. Es solo propiedad, no atributo: una función no cabe en un atributo.
html
<script src="https://<tu-backend-ur>/widget.js" data-agent="<id-del-agente>"></script>
<script>
document.querySelector('ur-agent-chat').getUserToken = async () => {
const res = await fetch('/ur-token', { credentials: 'same-origin' });
return res.ok ? res.text() : null; // sin sesión: habla anónimo
};
</script>- El widget manda el token como
Authorization: Bearer <token>en cada mensaje, al recuperar el historial y al pedir la bienvenida. Si el servidor responde que ha caducado, pide otro y repite la petición una vez. - Asígnala justo después del
<script>del widget: el elemento ya existe y todavía no ha pedido el historial, que sale cuando llega su configuración. Asignada más tarde, vale desde la petición siguiente. Como módulo, asígnala antes de poneragento de insertar el elemento. - Sin token (vacío o
null) habla anónimo, que solo vale si el agente tiene el usuario como opcional. Si lo exige, no recupera el historial y al escribir pinta el error en el chat.
La interfaz está en español
Los textos del propio widget —el placeholder del campo de escritura, «Reiniciar conversación», «Conversación finalizada», el título por defecto («Asistente virtual») y las etiquetas de accesibilidad de los botones— están fijos en español y no hay ningún atributo para cambiarlos. Lo único traducible desde fuera es el título de la cabecera, con data-title o desde la ficha del canal.
Si tu web está en otro idioma, hoy las opciones son dos: montar tu propia UI con el SDK —donde cada texto es tuyo—, o sobrescribir los textos por CSS y JavaScript desde fuera, que es frágil. Si lo necesitas, dínoslo: es una limitación conocida.
El mensaje automático del agente sí sale en el idioma del visitante si el agente lo tiene: el widget manda data-lang (o lang) o, sin él, los idiomas del navegador. Así, con la web en euskera, la bienvenida puede llegar en euskera y el resto de la interfaz seguir en castellano.
Detalles de uso
- Reiniciar la conversación es mantener pulsado el botón de reinicio ~2 segundos, no un clic. Es deliberado: evita perder el hilo por un toque accidental. Si el agente tiene límite de turnos, el botón no aparece.
- El panel se puede maximizar, con un tope de 800×800 px.
- El widget guarda la identidad de conversación en
localStorage, así que el usuario recupera su hilo al volver.
Límite de turnos
Si el agente tiene un máximo de turnos por conversación (ficha del agente → Seguridad), el widget lo lee de la configuración del canal al cargar y:
- No ofrece «Reiniciar conversación», porque una conversación nueva empezaría la cuenta de cero.
- Tras la respuesta al último turno pinta el mensaje Límite de conversación del catálogo en una burbuja propia, con un candado y el rótulo «Conversación finalizada», y deja la caja de texto visible pero deshabilitada. Si llegara texto después, se descarta.
- Al recargar la página, el cierre sigue ahí: el historial lo devuelve y la caja vuelve deshabilitada.
Si además el agente tiene «Olvidar la conversación tras (horas)», al cargar el widget mira cuándo envió el navegador el último mensaje; pasado ese plazo, empieza una conversación nueva en vez de restaurar la anterior. Esa marca de tiempo se guarda en localStorage como ur-widget-activity-<agente>, junto a ur-widget-subject-<agente>.
Nada de esto aplica cuando el widget abre una conversación concreta con el atributo subject.
Ver Seguridad y límites para qué cuenta como turno y qué pasa si cambias el límite.
Si el widget no te encaja
Cuando necesites tu propio diseño o integrarlo en una pantalla existente, la pieza de abajo es el SDK: SDK — quickstart.