Widgets para sitios web
Integra tu agente de voz IA en cualquier sitio web para que los visitantes puedan iniciar una conversación de voz directamente desde el navegador. La pestaña Widgets ofrece códigos de integración, opciones de personalización y ajustes de seguridad de dominio.
El Widget de devolución de llamada funciona de forma muy distinta a los widgets de esta página: en lugar de iniciar una llamada de voz en el navegador, recoge el número de teléfono del visitante y hace que tu agente lo llame de vuelta. Consulta la página dedicada Widget de devolución de llamada.
Tipos de widget
Hanc.AI ofrece cuatro tipos de widgets en navegador, además de un Widget de devolución de llamada independiente para llamadas telefónicas:
| Widget | Nombre de etiqueta | Descripción | Recomendado para |
|---|---|---|---|
| Widget flotante | hanc-ai-floating-call | Botón orbe que flota sobre tu página | Llamada a la acción siempre visible |
| Widget píldora | hanc-ai-pill-call | Botón compacto con forma de píldora colocado en línea en tu contenido | Huella mínima dentro de un diseño existente |
| Widget píldora flotante | hanc-ai-pill-floating-call | Misma forma compacta de píldora, pero flota con la página como el widget flotante | Cuando quieres una estética de píldora que siga al visitante al hacer scroll |
| Widget en línea | hanc-ai-inline-call | Botón de llamada de tamaño completo integrado en el contenido de la página | Secciones dedicadas "Habla con nosotros" |
| Widget de devolución de llamada | hanc-ai-callback | Formulario de número de teléfono; el agente llama de vuelta al visitante | Páginas de captación de leads, landings de alta intención: ver Widget de devolución de llamada |
Atributos comunes
Todos los tipos de widget admiten estos atributos básicos:
| Atributo | Obligatorio | Descripción | Predeterminado |
|---|---|---|---|
agent-id | Sí | Identificador único de tu agente | — |
voice-service-url | No | Sobrescribir la URL del servicio de voz | Detección automática |
api-base-url | No | Sobrescribir la URL base de la API | Detección automática |
Atributos de visualización
| Atributo | Descripción | Valores | Predeterminado |
|---|---|---|---|
position | Posición del widget en la página | bottom-right, bottom-left, top-right, top-left, static | bottom-right |
size | Tamaño del widget en píxeles | Número | 120 |
theme | Nombre del tema de color | Ver Temas de color | default |
Atributos de texto del botón
| Atributo | Descripción | Predeterminado |
|---|---|---|
button-start-text | Texto mostrado en el botón inactivo | "Call" |
button-connecting-text | Texto mostrado durante la conexión | "Connecting..." |
button-end-text | Texto mostrado durante una llamada activa | — |
Atributos de términos
| Atributo | Descripción | Predeterminado |
|---|---|---|
terms-enabled | Activa el diálogo de consentimiento antes de la llamada | false |
terms-content | Texto de consentimiento en formato Markdown | "" |
terms-url | Enlace a tu página de Términos y Condiciones | "https://hanc.ai/terms" |
privacy-url | Enlace a tu página de Política de Privacidad | "https://hanc.ai/privacy" |
Los atributos de términos definidos en el elemento HTML son sobrescritos por la configuración de widget del agente obtenida desde la API, a menos que skip-fetch esté en true.
Atributos de sonido
| Atributo | Descripción | Predeterminado |
|---|---|---|
sound-enabled | Activa los sonidos de inicio/fin de llamada | true |
sound-volume | Volumen de los efectos de sonido | 0.25 |
sound-preset | Identificador del preset de sonido | "1" |
Temas de color
Personaliza la apariencia del widget con 11 temas de color integrados:
| Tema | Valor |
|---|---|
| Predeterminado | default |
| Púrpura | purple |
| Azul | blue |
| Cian | cyan |
| Esmeralda | emerald |
| Ámbar | amber |
| Mandarina | tangerine |
| Rosa | rose |
| Brasa | ember |
| Negro | black |
| Blanco | white |
Cada tema tiene variantes oscura y clara. Define el tema mediante el atributo theme en el código de integración, o configúralo en los ajustes de widget del agente.
Ejemplos de integración
Widget flotante
<hanc-ai-floating-call agent-id="YOUR_AGENT_ID"></hanc-ai-floating-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async type="text/javascript"></script>
Widget flotante con tema y posición
<hanc-ai-floating-call
agent-id="YOUR_AGENT_ID"
theme="emerald"
position="bottom-left"
size="140"
></hanc-ai-floating-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async type="text/javascript"></script>
Widget píldora
<hanc-ai-pill-call agent-id="YOUR_AGENT_ID"></hanc-ai-pill-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async type="text/javascript"></script>
Widget en línea
<hanc-ai-inline-call agent-id="YOUR_AGENT_ID"></hanc-ai-inline-call>
<script src="https://unpkg.com/hanc-webrtc-widgets" async type="text/javascript"></script>
La URL del script anterior siempre carga el último widget publicado: tu sitio recibe mejoras automáticamente, y @latest es el valor predeterminado cuando no se especifica versión. Si necesitas bloquearlo a una versión fija, indícalo explícitamente añadiendo la versión que quieras, p. ej. https://unpkg.com/hanc-webrtc-widgets@X.Y.Z.
Eventos del widget
Los widgets emiten eventos que puedes escuchar en JavaScript:
| Evento | Descripción |
|---|---|
status-changed | Se dispara cuando cambia el estado de la llamada |
connecting | Se está estableciendo la llamada |
connected | La llamada está activa |
idle | No hay llamada activa |
error | Ocurrió un error |
audio-track | Se recibió la pista de audio remoto (para visualización) |
local-audio-track | Pista de audio del micrófono local (para visualización) |
microphone-enabled | Se activó el micrófono |
microphone-disabled | Se desactivó el micrófono |
call-start | Se dispara cuando una llamada se inicia correctamente |
call-end | Se dispara cuando finaliza la llamada |
Ejemplo: escuchar eventos
const widget = document.querySelector('hanc-ai-floating-call');
widget.addEventListener('call-start', () => {
console.log('Call started');
});
widget.addEventListener('call-end', () => {
console.log('Call ended');
});
Permitir que el agente abra páginas
Durante una llamada desde el navegador, el agente puede pedirle a su sitio que abra una página —«déjeme mostrarle los precios»— y el visitante lo ve sin interrumpir la conversación.
Su página manda. El agente envía una petición; su código decide qué significa. Abrir una URL, cambiar de pestaña, desplazarse a una sección y desplegar un acordeón son todas respuestas válidas.
Son tres pasos, y ninguno funciona por separado.
Paso 1 — Dígale al agente qué páginas existen
El agente no ve el mapa de su sitio. Solo pide rutas que usted le haya dado, así que enumérelas en el prompt del agente o en la base de conocimiento:
Páginas de nuestro sitio:
/pricing — planes y precios
/contact — formulario de contacto y teléfono
/product/crm — el CRM
Si se salta este paso, el agente no tiene nada que pedir y ni siquiera lo intenta.
Paso 2 — Atienda la petición en su página
Añada esto una vez, en cualquier punto después del script del widget. El evento sube por la página, así que document es un buen sitio para escucharlo:
<script>
document.addEventListener('agent-command', (event) => {
const { type, payload } = event.detail;
if (type === 'navigate') {
// SPA: navegar sin recargar — la llamada continúa.
router.push(payload.path);
// Sitio clásico: abrir una segunda pestaña; esta (y la llamada) sigue viva.
// window.open(payload.path, '_blank');
event.preventDefault(); // ← así le dice al agente que lo atendió
}
});
</script>
La llamada vive en esta página. window.location.href = … descarga el documento y la conversación se va con él: el visitante queda cortado a media frase. Si tiene un router, navegue en el cliente; si no, abra la página en una pestaña nueva. No hay reconexión: nada sobrevive a una recarga.
preventDefault() no es opcionalEs la única forma de decir «me he encargado». Sin él, al agente se le informa de que el sitio no admite navegación: deja de intentarlo durante el resto de la llamada y vuelve a explicar dónde hacer clic. En la consola no aparece nada: la página simplemente parece haber ignorado la petición, porque la ignoró.
Paso 3 — Pruébelo
Llame a su agente desde el sitio y pídale una página por su nombre. Deben ocurrir dos cosas: la página se abre y el agente dice algo como «aquí están los precios» en lugar de «los encontrará en el menú».
Responder al agente con datos
Algunos comandos son preguntas, no instrucciones. Llegan igual, pero se contestan con respond():
| Comando | Qué pregunta el agente | Con qué responde usted |
|---|---|---|
navigate | «abre esta ruta» | con nada: basta preventDefault() |
page_context | «¿qué está viendo el visitante?» | lo que sea útil: ruta, título, producto |
cart_state | «¿qué tiene en el carrito?» | artículos, totales, moneda |
<script>
document.addEventListener('agent-command', (event) => {
const { type, respond } = event.detail;
if (type === 'page_context') {
event.preventDefault();
respond({ path: location.pathname, title: document.title });
}
});
</script>
Tras preventDefault() dispone de alrededor de un segundo para responder: un await está bien, una llamada lenta a una API no. Responda con lo que ya tenga a mano.
Qué puede y qué no puede pedir el agente
- Solo rutas de su propio sitio. La ruta debe empezar por
/. Todo lo que pudiera salir de su dominio —//evil.com,https://…, barras invertidas— se rechaza antes de llegar a su página. Un agente no puede llevarse a sus visitantes a otra parte. - Solo llamadas desde el navegador. En una llamada telefónica no hay página que abrir, así que allí estos comandos no existen.
- Una negativa basta. Si su página no confirma la primera petición, el agente deja de preguntar durante el resto de la llamada. No insistirá y —más importante— no le dirá al visitante que abrió algo que no abrió.
Registre cada comando antes de filtrarlo: document.addEventListener('agent-command', e => console.log(e.detail)). Si ve navigate en la consola, el agente cumplió su parte y lo que falta es preventDefault() o su propio handler. Si no ve nada, al agente nunca se le dijo que esa ruta existe: vuelva al paso 1.
Requisitos técnicos
Los widgets requieren que el navegador del visitante admita:
- WebGL 2.0: para renderizado
- Web Audio API: para procesamiento de audio
- WebRTC: para comunicación de voz en tiempo real
Todos los navegadores modernos (Chrome, Firefox, Safari, Edge) admiten estas tecnologías.
Restricciones de dominio
Controla qué sitios web pueden integrar el widget de tu agente.
Dominios siempre permitidos
Los siguientes dominios siempre están permitidos independientemente de la configuración:
hanc.ai(y subdominios)hanc.me(y subdominios)localhost
Permitir todos los dominios
Por defecto, tu widget puede integrarse en cualquier sitio web. Activa "Permitir todos los dominios" en los ajustes del widget para restringirlo.
Restringir a dominios específicos
Cuando esté restringido, añade cada dominio que deba permitirse:
- Introduce los nombres de dominio sin
https://(p. ej.,example.com) - Los subdominios necesitan entradas separadas (p. ej.,
www.example.com,shop.example.com) - Se pueden especificar puertos (p. ej.,
localhost:3000) - Se pueden incluir como máximo 50 dominios en la lista blanca
Para agentes en producción, restringe los widgets a tus propios dominios para evitar integraciones no autorizadas.
Términos y condiciones
Activa un diálogo de consentimiento antes de que los llamantes puedan iniciar una conversación.
Configuración
| Ajuste | Descripción |
|---|---|
| Activar términos | Activa o desactiva el diálogo de términos |
| Contenido de los términos | Texto de consentimiento en formato Markdown mostrado a los usuarios (máx. 5.000 caracteres) |
| URL de términos | Enlace a tu página completa de Términos y Condiciones |
| URL de privacidad | Enlace a tu página de Política de Privacidad |
Cuando está activado:
- Los usuarios ven un diálogo de consentimiento antes de iniciar una llamada
- Deben hacer clic en "Aceptar" para continuar
- El consentimiento se almacena localmente en el navegador
- El botón Restablecer consentimiento borra el consentimiento almacenado para pruebas
Formato del contenido
El contenido de los términos admite formato Markdown:
- Usa
####para encabezados - Usa
**negrita**para énfasis - Usa saltos de línea para mejorar la legibilidad
Relacionado
- Widget de devolución de llamada: devoluciones de llamada para visitantes que prefieren no hablar en el navegador
- Visión general de agentes de voz IA
- Ajustes: ajustes del agente incluida la configuración del widget
- Integraciones: claves API y configuración de números de teléfono