Inserción avanzada
Temas para desarrolladores que integran Asktopus en un stack más exigente: Content-Security-Policy, aplicaciones de una sola página (SPA) y la API programática. Para lo básico, consulta la guía de instalación.
Content-Security-Policy
Si tu web envía una cabecera Content-Security-Policy, el widget necesita tres directivas para cargarse y conectarse: - script-src debe permitir nuestra CDN, https://cdn.asktopus.com - connect-src debe permitir https://api.asktopus.com para descargar la configuración y wss://api.asktopus.com para el WebSocket del chat - style-src necesita 'unsafe-inline' o un nonce para los estilos que inserta el widget
Content-Security-Policy:
script-src 'self' https://cdn.asktopus.com;
connect-src 'self' https://api.asktopus.com wss://api.asktopus.com;
style-src 'self' 'unsafe-inline';El widget se muestra dentro de un Shadow DOM, pero la CSP de la página que lo aloja sigue aplicándose a los elementos style que inserta: añadir 'unsafe-inline' a style-src es la solución más sencilla. Si no puedes permitir estilos en línea, escríbenos y buscaremos contigo una configuración basada en nonce.
Shadow DOM y estilos
El widget se monta dentro de una raíz Shadow DOM cerrada. Eso te da una garantía: nada de tu página (CSS global, estilos del framework, personalizaciones del tema) puede colarse y romper el diseño del widget. La otra cara es que tampoco puedes cambiar el estilo del widget desde fuera; el estilo se configura en el panel (color principal, posición, icono del encabezado). Si necesitas una personalización visual que el panel no ofrece, escríbenos: la mayoría de las peticiones se pueden resolver con una nueva opción en el panel en lugar de un desarrollo a medida.
Aplicaciones de una sola página y cambios de ruta
El widget se monta directamente en document.body, no dentro del componente raíz de tu framework. Los cambios de ruta en el cliente no lo desmontan: se queda en su sitio mientras se navega, que es lo que quieres. Si tu aplicación hace algo poco habitual (reescribir document.body, renderizados completos que desenganchan elementos ajenos), el widget puede desaparecer tras un cambio de ruta. Solución provisional: llama a window.Asktopus.destroy() y vuelve a ejecutar el script de inserción. Estamos trabajando en una API de reinicialización más limpia; avísanos si te ocurre.
API programática
Una vez cargado, el widget expone tres métodos en window.Asktopus:
// Open the chat programmatically (e.g., from a "Help" button)
document.querySelector('#help-button')
.addEventListener('click', () => window.Asktopus.open())
// Close it
window.Asktopus.close()
// Remove the widget entirely (e.g., before re-initializing in an SPA)
window.Asktopus.destroy()Estos métodos solo están disponibles cuando el widget ya se ha iniciado (después de DOMContentLoaded). Si asignas un manejador de clic que llama a window.Asktopus.open() durante la carga de la página, comprueba que el objeto global no sea undefined o espera a que aparezca window.Asktopus.
Forzar un idioma concreto
Por defecto, el widget lee el atributo html lang de la página, después el idioma del navegador del visitante y, si no hay ninguno, usa el inglés. Para forzar otro idioma, asigna a window.__ASKTOPUS_LANG un código de 2 letras antes de que se ejecute el script de inserción. Sobre todo es útil para vistas previas y pruebas; en producción, lo correcto es definir bien html lang.
async, defer o lazyOnload
El fragmento predeterminado usa async, que permite al navegador descargar el script mientras analiza el HTML y ejecutarlo en cuanto llega. Es la opción adecuada para la gran mayoría de las webs: es rápida, no bloquea el renderizado y el widget aparece lo antes posible. Si lo que buscas es que la página se pinte lo más rápido posible y no te importa que el widget aparezca un instante después, usa defer o strategy="lazyOnload" de Next.js. El widget se inicializa por sí mismo en cuanto el DOM está listo, sea cual sea la estrategia de carga que elijas.