Guía de integración

Integra el asistente en tu sitio

Hay cuatro métodos de integración: código QR, enlace directo, widget flotante y embed inline. Elige el que mejor se ajuste a tu sitio y no mezcles sus configuraciones. Esta guía cubre los cuatro, con código listo para React, Next.js, Vue, Nuxt, Svelte, Angular y cualquier CMS.

Configuración

Identificador y direcciones

Cada asistente tiene un identificador único (slug). Lo encuentras en el panel de administración, en el detalle del bot, pestaña Integración. En los ejemplos de esta guía se usa el valor de referencia tu-asistente; reemplázalo por el real.

bot-slug
Identificador del asistente. Ej.: tu-asistente
https://bot.alteria.dev/<slug>
URL pública del asistente (chat a pantalla completa, QR o iframe).
https://bot.alteria.dev/widget.js
Script del Web Component (widget flotante e inline).
https://bot-service.alteria.dev
API del servicio (atributo api-url).
El panel de administración muestra estos valores ya rellenados con el slug real y ofrece copiar al portapapeles en cada bloque de código.
01

Código QR

Genera una señalética imprimible con el código QR del asistente. Al escanearlo, el cliente abre el chat a pantalla completa en su teléfono. Ideal para tiendas físicas, mesones de atención, vitrinas, empaques o material impreso.

Cómo se genera
En la pestaña Integración del bot, abre la tarjeta Código QR y pulsa Desplegar QR. Luego Descargar PNG para obtener la señalética completa (1080×1920, lista para imprimir o compartir).
A dónde apunta
A la URL pública del asistente: https://bot.alteria.dev/tu-asistente
Cuándo usarlo
Tiendas físicas y puntos de atención presencial, material impreso (folletos, vitrinas, empaques, boletas) y pantallas en local o eventos.
La señalética incluye el nombre del asistente, un titular de invitación ("¡Pregúntame lo que quieras!"), el QR real embebido y tres destacados: respuestas al instante, atención 24/7 y sin esperas.
02

Enlace directo (pantalla completa)

Abre el chat como una página completa. Ideal para compartir el enlace directamente (redes, email, WhatsApp) o para insertarlo dentro de un iframe en tu sitio.

URL pública del asistente
https://bot.alteria.dev/tu-asistente
Insertar dentro de un iframe · pegar en el HTML donde se quiere mostrar el chat
<iframe
  src="https://bot.alteria.dev/tu-asistente"
  width="100%"
  height="600"
  style="border:none;border-radius:12px"
  allow="microphone"
></iframe>
src="..."
URL pública del asistente que se cargará dentro del iframe.
width="100%"
Ocupa todo el ancho disponible del contenedor.
height="600"
Altura visible del asistente en píxeles.
style="border:none;..."
Sin borde y con esquinas redondeadas para integrarse al diseño.
allow="microphone"
Permite el micrófono si el asistente usa funciones de voz.
03

Widget flotante

Muestra un botón flotante en una esquina de la pantalla. Al hacer clic, se abre el chat en un panel. El asistente queda disponible en todo el sitio sin ocupar espacio dentro del contenido. Es la opción recomendada para ecommerce.

Instalación en HTML · pegar antes del cierre de </body>
<script src="https://bot.alteria.dev/widget.js"></script>
<chat-widget
  bot-slug="tu-asistente"
  api-url="https://bot-service.alteria.dev"
  theme="auto"
  position="bottom-right"
  mode="floating"
></chat-widget>
bot-slug (requerido)
Identificador del asistente.
api-url (requerido)
URL del servicio: https://bot-service.alteria.dev
theme
auto · light · dark. Con auto sigue el tema del navegador.
position
bottom-right (recomendado) · bottom-left · top-right · top-left
mode
floating (botón flotante).
Tamaño del panel: 380×550px (responsive en móvil). No necesita contenedor, se posiciona solo.

Inyectores por stack

El panel de administración genera el inyector para cada framework. Móntalo una sola vez en la raíz de la app; no renderiza nada visible: el chat se inserta directo en <body>.

React — ChatWidget.tsx
// Monta este componente UNA vez en tu App (ej. App.tsx).
import { useEffect } from 'react'

export function ChatWidget() {
  useEffect(() => {
    // Evita doble carga (HMR, StrictMode, navegación SPA).
    if (document.getElementById('alteria-widget-script')) return
    const s = document.createElement('script')
    s.id = 'alteria-widget-script'
    s.src = 'https://bot.alteria.dev/widget.js'
    s.async = true
    s.onload = () => {
      const el = document.createElement('chat-widget')
      el.setAttribute('bot-slug', 'tu-asistente')
      el.setAttribute('api-url', 'https://bot-service.alteria.dev')
      el.setAttribute('mode', 'floating')
      el.setAttribute('theme', 'auto')
      el.setAttribute('position', 'bottom-right')
      document.body.appendChild(el)
    }
    document.head.appendChild(s)
  }, [])
  return null
}
Next.js — app/components/ChatWidget.tsx
'use client' // Client Component. Impórtalo en app/layout.tsx dentro del <body>.
import { useEffect } from 'react'

export function ChatWidget() {
  useEffect(() => {
    if (document.getElementById('alteria-widget-script')) return
    const s = document.createElement('script')
    s.id = 'alteria-widget-script'; s.src = 'https://bot.alteria.dev/widget.js'; s.async = true
    s.onload = () => {
      const el = document.createElement('chat-widget')
      el.setAttribute('bot-slug', 'tu-asistente')
      el.setAttribute('api-url', 'https://bot-service.alteria.dev')
      el.setAttribute('mode', 'floating'); el.setAttribute('theme', 'auto')
      el.setAttribute('position', 'bottom-right')
      document.body.appendChild(el)
    }
    document.head.appendChild(s)
  }, [])
  return null
}
Vue 3 — ChatWidget.vue
<!-- Inclúyelo una vez en App.vue: <ChatWidget /> -->
<script setup>
import { onMounted } from 'vue'
onMounted(() => {
  // onMounted solo corre en el cliente (no en SSR).
  if (document.getElementById('alteria-widget-script')) return
  const s = document.createElement('script')
  s.id = 'alteria-widget-script'; s.src = 'https://bot.alteria.dev/widget.js'; s.async = true
  s.onload = () => {
    const el = document.createElement('chat-widget')
    el.setAttribute('bot-slug', 'tu-asistente')
    el.setAttribute('api-url', 'https://bot-service.alteria.dev')
    el.setAttribute('mode', 'floating'); el.setAttribute('theme', 'auto')
    el.setAttribute('position', 'bottom-right')
    document.body.appendChild(el)
  }
  document.head.appendChild(s)
})
</script>
Nuxt — plugins/chat-widget.client.ts
// plugins/chat-widget.client.ts
// El sufijo .client.ts es CRÍTICO: hace que corra solo en el navegador.
export default defineNuxtPlugin(() => {
  if (document.getElementById('alteria-widget-script')) return
  const s = document.createElement('script')
  s.id = 'alteria-widget-script'; s.src = 'https://bot.alteria.dev/widget.js'; s.async = true
  s.onload = () => {
    const el = document.createElement('chat-widget')
    el.setAttribute('bot-slug', 'tu-asistente')
    el.setAttribute('api-url', 'https://bot-service.alteria.dev')
    el.setAttribute('mode', 'floating'); el.setAttribute('theme', 'auto')
    el.setAttribute('position', 'bottom-right')
    document.body.appendChild(el)
  }
  document.head.appendChild(s)
})
Svelte — ChatWidget.svelte
<!-- ChatWidget.svelte — impórtalo en +layout.svelte -->
<script>
  import { onMount } from 'svelte'
  onMount(() => {
    if (document.getElementById('alteria-widget-script')) return
    const s = document.createElement('script')
    s.id = 'alteria-widget-script'; s.src = 'https://bot.alteria.dev/widget.js'; s.async = true
    s.onload = () => {
      const el = document.createElement('chat-widget')
      el.setAttribute('bot-slug', 'tu-asistente')
      el.setAttribute('api-url', 'https://bot-service.alteria.dev')
      el.setAttribute('mode', 'floating'); el.setAttribute('theme', 'auto')
      el.setAttribute('position', 'bottom-right')
      document.body.appendChild(el)
    }
    document.head.appendChild(s)
  })
</script>
Angular — chat-widget.component.ts
// chat-widget.component.ts — usa <app-chat-widget> en app.component.html
import { Component, OnInit } from '@angular/core'

@Component({ selector: 'app-chat-widget', standalone: true, template: '' })
export class ChatWidgetComponent implements OnInit {
  ngOnInit(): void {
    if (document.getElementById('alteria-widget-script')) return
    const s = document.createElement('script')
    s.id = 'alteria-widget-script'; s.src = 'https://bot.alteria.dev/widget.js'; s.async = true
    s.onload = () => {
      const el = document.createElement('chat-widget')
      el.setAttribute('bot-slug', 'tu-asistente')
      el.setAttribute('api-url', 'https://bot-service.alteria.dev')
      el.setAttribute('mode', 'floating'); el.setAttribute('theme', 'auto')
      el.setAttribute('position', 'bottom-right')
      document.body.appendChild(el)
    }
    document.head.appendChild(s)
  }
}
04

Embed inline (en contenedor)

Integra el chat directamente dentro de un contenedor de tu página. Sin botón flotante: se adapta al tamaño del contenedor. Usa el mismo script y componente, cambiando mode a inline.

Instalación en HTML · pegar dentro de la sección donde irá el chat
<script src="https://bot.alteria.dev/widget.js"></script>
<!-- Ajusta width y height. ALTURA OBLIGATORIA. -->
<div style="width:400px;height:600px">
  <chat-widget
    bot-slug="tu-asistente"
    api-url="https://bot-service.alteria.dev"
    theme="auto"
    mode="inline"
  ></chat-widget>
</div>
Reglas del contenedor: debe tener ancho y altura definidos (px, vh o %); no usar height:auto. El chat ocupa el 100% del contenedor. Altura mínima recomendada: 400px. Ejemplos: 100%/100vh (pantalla completa) o 350px/500px (sidebar).

Inyectores por stack (inline)

Cada framework usa el mismo inyector del widget flotante, con dos cambios: mode='inline' y montar el <chat-widget> dentro de un contenedor con altura definida (en vez de document.body). Ejemplo en React:

React — ChatWidgetInline.tsx
import { useEffect, useRef } from 'react'

export function ChatWidgetInline() {
  const ref = useRef<HTMLDivElement>(null)
  useEffect(() => {
    const mount = () => {
      if (!ref.current || ref.current.querySelector('chat-widget')) return
      const el = document.createElement('chat-widget')
      el.setAttribute('bot-slug', 'tu-asistente')
      el.setAttribute('api-url', 'https://bot-service.alteria.dev')
      el.setAttribute('mode', 'inline'); el.setAttribute('theme', 'auto')
      ref.current.appendChild(el) // se monta DENTRO del contenedor
    }
    if (document.getElementById('alteria-widget-script')) { mount(); return }
    const s = document.createElement('script')
    s.id = 'alteria-widget-script'; s.src = 'https://bot.alteria.dev/widget.js'; s.async = true; s.onload = mount
    document.head.appendChild(s)
  }, [])
  return <div ref={ref} style={{ width: 400, height: 600 }} /> // altura obligatoria
}
Referencia rápida

Resumen de los cuatro métodos

Código QR

Qué instala
Señalética PNG con QR
Dónde
Impreso / pantalla
Uso ideal
Tienda física, material impreso

Enlace directo

Qué instala
URL · <iframe>
Dónde
Página / iframe
Uso ideal
Chat a pantalla completa, compartir enlace

Widget flotante

Qué instala
<script> + <chat-widget mode="floating">
Dónde
Antes de </body>
Uso ideal
Ecommerce, disponible en todo el sitio

Embed inline

Qué instala
<script> + <div> + <chat-widget mode="inline">
Dónde
Contenedor con alto/ancho
Uso ideal
Sección de ayuda, sidebar
El snippet HTML funciona en cualquier plataforma donde puedas pegar código: WordPress/WooCommerce, Shopify (theme.liquid), VTEX, Jumpseller, Wix, Google Tag Manager, etc. Para disponibilidad global, insértalo en la plantilla común del sitio.
Regla simple para evitar errores: con enlace directo usas solo la URL pública. Con flotante o inline usas siempre el mismo script (widget.js) y configuras todo con atributos dentro de <chat-widget>. No mezcles métodos en la misma integración.
Seguridad

Seguridad y dominios permitidos

El asistente aplica una lista de dominios permitidos (allowlist CORS). El servicio solo responde a los sitios cuyo dominio ha sido registrado y activado. Es el requisito de seguridad más importante para que la integración funcione.

Antes de publicar: el dominio (origin) de tu sitio debe estar registrado y activo en la allowlist de Alteria. Si no lo está, el asistente no cargará y el navegador bloqueará las llamadas por CORS.

Qué es un "origin"

Un origin es la combinación de esquema + dominio (+ puerto). Se registran de forma exacta, así que conviene declarar todas las variantes que use tu sitio:

https://www.tusitio.cl
Dominio con www.
https://tusitio.cl
Dominio sin www (si también responde ahí).
https://tienda.tusitio.cl
Subdominios adicionales, si corresponde.
Envía a tu contacto en Alteria la lista de dominios donde se publicará el asistente. Los cambios se gestionan desde el panel de administración (módulo Allowed Origins).

Nivel de seguridad de la integración

Sin claves secretas
El código embebido solo usa el slug público y la URL del servicio. No expone tokens ni credenciales en el HTML del sitio.
CORS por dominio
El servicio solo atiende solicitudes desde orígenes permitidos y activos.
HTTPS obligatorio
Todo el tráfico (widget y API) viaja cifrado.
Micrófono opt-in
El micrófono solo se solicita si se declara allow="microphone" y el usuario lo autoriza.
Aislamiento por asistente
Cada bot-slug queda acotado a su propio catálogo e identidad.

Checklist antes de publicar

  • Reemplazar tu-asistente por el slug real del asistente.
  • Confirmar que el dominio del sitio está en la allowlist y activo.
  • Verificar que el sitio se sirve por HTTPS.
  • Elegir un solo método; no mezclar enlace directo, flotante e inline.
  • En frameworks con SSR (Next.js, Nuxt), montar el widget solo en el cliente.
  • Confirmar con Alteria que el catálogo de tu plataforma quedó ingerido y verificado.
  • Probar en escritorio y móvil.

¿Aún no tienes tu asistente? Créalo primero: conectamos tu catálogo y queda listo para integrar en pocas horas. El primer mes es gratis.

Empezar en mi tienda o prueba la demo en vivo →