Widget web
Actualizado 2026-10-06
Una línea en tu sitio y aparece una burbuja de chat en una esquina: tus visitantes le escriben a tu agente, sin cuenta. Su apariencia (nombre, avatar, colores, tipografía, lado, sugerencias) la cambias sin volver a pegar el código.
Encenderlo
Desde Agentes → tu agente → Canales → Widget web: prende el switch, escribe tus dominios y copia el código. O desde la terminal:
Te devuelve el código para pegar antes de </body>:
Funciona igual en HTML a mano, WordPress, Shopify, Wix o cualquier sitio que te deje pegar un <script>.
Dónde carga: tus dominios
El widget sólo se abre en los dominios que pongas. Si alguien copia tu código en otro sitio, el navegador no lo carga.
mitienda.comtambién vale parawww.mitienda.com.*.mitienda.comvale para cualquier subdominio (blog.mitienda.com,tienda.mitienda.com).- Sin dominios no carga en ningún lado.
- Sólo
https.
Qué puede hacer el visitante
- Sólo conversar con tu agente. Cada visitante tiene su conversación y no ve la de nadie más; el agente corre aislado por visitante.
- Habla como cliente: consulta tus bases y documentos según lo que le diste al canal, pero no administra (no toca tableros, correos ni bases sin permiso de escritura).
- Su conversación se guarda en su navegador y sigue donde la dejó al volver.
- Cada mensaje entra a tu CRM como conversación del canal web.
Personalizarlo
Todo se cambia en Canales → Widget web, por API (PATCH /api/v2/agents/{id}/embed) o desde la terminal. El código que ya pegaste no cambia: la burbuja pide su apariencia al cargar (tarda hasta un minuto en verse el cambio).
El avatar se copia a img.ghosty.studio: si tu imagen cambia de liga, el widget no se queda con un hueco.
Estilo fino
Para que se vea igual que tu sitio, el bloque style cambia la tipografía, las esquinas y el color de cada pieza. No acepta CSS libre: sólo estas llaves, cada una validada. Una llave en null vuelve a su default; --style none resetea todo.
Llave | Qué cambia | Cómo se ve |
|---|---|---|
fontFamily | Tipografía de Google Fonts de una lista: Inter, Barlow, Barlow Condensed, Poppins, Montserrat, Roboto, Open Sans, Lato, Nunito, DM Sans, Work Sans, Manrope, Rubik, IBM Plex Sans, Source Sans 3, Raleway, Merriweather, Lora, Playfair Display, Libre Baskerville, Cormorant Garamond, Space Grotesk, Source Serif 4 | AaAaAa |
radius | Esquinas del panel, las burbujas, la caja y el botón de enviar (0–24 px; 0 = rectas) | |
headerBg · headerText | Fondo y texto del encabezado | Asistente |
titleUppercase | Título en MAYÚSCULAS con espaciado | Asistente |
statusDot | Punto de estado junto al título (color) | Asistente |
headerAvatar | false quita el avatar del encabezado | |
panelBg | Fondo del panel | |
userBubbleBg · userBubbleText | Burbuja del visitante | ¿Tienen envíos? |
agentBubbleBg · agentBubbleText | Burbuja del agente (sin ella, el agente escribe sin burbuja) | ¡Claro! |
inputBg | Caja para escribir | Escribe… |
sendBg · sendIcon · sendArrow | Botón de enviar, su flecha y su dirección ( up o right) | ↑→ |
launcherBg · launcherIcon | Botón flotante (siempre redondo) | |
typing · typingColor | Los puntitos de «escribiendo» mientras responde: bounce (rebote, el de siempre), flow (ola), flashing (parpadeo) o shimmer («Pensando…» con brillo, sin puntos), y su color (sin él, el de tu marca) |
Los colores van en #rrggbb. Un texto que no pongas se calcula por contraste contra su fondo.
Ejemplo: estilo Palmera Legal — encabezado verde con el título en mayúsculas, punto dorado, todo en esquinas rectas, burbujas verde y beige, Barlow y puntitos dorados en ola:
--font y --radius son atajos de style.fontFamily y style.radius.
Puntitos de «escribiendo»
Mientras el agente responde, el chat muestra tres puntitos. Por defecto toman el color de tu marca (el del encabezado). Con --typing-color les pones otro y con --typing cambias la animación:
typing | Qué hace | Cómo se ve |
|---|---|---|
bounce | Rebotan uno tras otro (el de siempre) | |
flow | Crecen en ola | |
flashing | Parpadean, como en WhatsApp | |
shimmer | Sin puntos: el «Pensando…» con un brillo que lo recorre | Pensando |
--typing-color none regresa al color de la marca. En la ficha del agente está en Canales → Widget web → Avanzado.
De dónde sale el tema
En la tarjeta eliges Nuevo (tus valores), De Teams o De mi sitio, con una vista previa:
- De Teams: toma la marca activa de tu espacio de Ghosty Teams (Ajustes → Marca): el primario va al encabezado, al botón y a la burbuja del visitante; el acento, al botón de enviar y al punto de estado; la superficie, al fondo; y su tipografía si está en la lista.
- De mi sitio: lee los colores y la tipografía del CSS de tu página (no de imágenes). Si tu sitio pinta todo con JavaScript, avisa que no encontró colores.
Los dos se importan como valores editables: después ajustas lo que quieras en Avanzado → Estilo. Para refrescarlos, vuelve a aplicarlos.
Textos mientras trabaja
Mientras el agente piensa, el widget enseña unas frases con la voz de Ghosty («Me estoy poniendo los lentes 👓», «Estoy abriendo mi libreta», «Estoy pensando»…). Si no van con tu negocio, cámbialas en la tarjeta (Avanzado → Textos, con vista previa), por API (copy) o con el CLI. Lo que no cambies sigue con la frase de Ghosty.
Texto plano de una línea, hasta 80 caracteres (sin < ni >). Es un PATCH por llave: null regresa esa frase a la de Ghosty y --copy none las regresa todas. Una llave que no existe o un texto largo contesta 400 con el motivo.
Ejemplo, un despacho («Palmera Legal»):
agents embed <id> theme exporta también copy, y --style-file lo vuelve a aplicar.
React
Si tu sitio es React (Next.js, Remix, Vite…), tienes tres caminos. Los tres hablan con el mismo agente y respetan tus dominios y topes.
ghosty agents embed <agent-id> imprime este snippet ya con tu token (y en --json, en el campo react).
La burbuja: <GhostyWidget>
Se monta y se limpia con el componente. Toma la apariencia guardada y lo que pases en props le gana: position, offsetX, offsetY, bubbleText, defaultOpen, open + onOpenChange (controlado), style con las mismas llaves de (también las del interior: burbujas, caja y enviar, que se validan igual que al guardarlas) y copy con las de (copy={{ thinking: ["Revisando su consulta…"] }}).
Tu propio chat: useGhostyChat
messages:{ id, role: "user" | "assistant", text, pending? }; el texto del agente llega en vivo.status:connecting·idle·thinking(mandado, sin texto todavía) ·streaming.error: los topes y avisos llegan como texto listo para enseñar («Llegaste al límite de mensajes por hoy…»).copy: tus (completos, con los de Ghosty donde no cambiaste nada) para pintar tu propia espera:copy?.thinking[0].nullhasta que llegan.- Al volver,
messagestrae la conversación anterior del visitante (un id por navegador enlocalStorage, llaveghosty:widget:vid).
Tu propio componente: --out
Si prefieres no depender de un paquete (estilo shadcn), el CLI escribe en tu proyecto un componente completo y editable, con tu token y tu tema actual (colores, tipografía, esquinas, título, placeholder, bienvenida, sugerencias y tus textos de espera) como constantes arriba del archivo, y comentarios que dicen dónde cambiar cada cosa:
No pisa un archivo que ya existe sin --force. Trae useGhostyChat() (la lógica) y GhostyChat (la UI) por separado: cambia la UI sin tocar la conexión.
Dominios y CORS
Desde tu página, las peticiones del modo headless y del componente van directo a Ghosty: sólo pasan si el Origin está en tus dominios del widget (mismas reglas: mitienda.com incluye www., *.mitienda.com sus subdominios, sólo https). Cualquier otro sitio recibe 403 y el navegador le bloquea la respuesta. En localhost no funciona: prueba en un dominio autorizado (o usa <GhostyWidget>, que vive en el iframe).
Topes y costo
Los turnos se cobran a tu cuenta, como cualquier otro canal. Para que nadie te los queme:
Si tu plan o tu llave no alcanzan, el visitante ve «no disponible por ahora» y tú ves el motivo con ghosty agents embed <agent-id>.
Cambiar o apagar
Requisitos
- Motor Claude o MiniGhosty (ghosty-lite): son los que aíslan a cada visitante. Con otro motor no se puede encender.
Agentes de EasyBits
Los agentes creados en Agentes → EasyBits siguen con su widget de siempre: un <iframe> con su token de embed.