En resumen
Pega el script de una línea de Nexoply en el index.html de tu app, justo antes de </body>, y el botón de chat aparece en todas las rutas. Si prefieres cargarlo desde el código (por ejemplo después del consentimiento de cookies, o con la clave en una variable de entorno), agrega el script desde un useEffect en tu componente raíz. No hay paquete npm que instalar ni clave de IA que administrar: el widget es un solo script asíncrono.
- Lo más simple: una etiqueta script en index.html antes de </body> (Vite: index.html en la raíz del proyecto; Create React App: public/index.html).
- Desde el código: un useEffect en tu componente raíz que agrega el script una vez. No necesita limpieza, y la doble ejecución de StrictMode no causa problemas.
- Se monta en document.body dentro de un Shadow DOM, fuera de tu raíz de React, así que los re-renders, los cambios de ruta y tu CSS nunca lo afectan.
- Abre el chat desde tu propio botón con window.dispatchEvent(new Event("nexoply:open-chat")).
- ¿Pruebas en localhost? Agrega tu host de desarrollo con su puerto a los sitios permitidos, o deja esa lista vacía.
Antes de empezar
Necesitas dos cosas antes de tocar el código:
- Una cuenta de Nexoply y la clave de tu chatbot. Regístrate gratis (el plan Free incluye 100 conversaciones al mes, sin tarjeta) y abre Chatbot en el panel. El código de instalación de esa página ya trae tu clave. La clave es pública: no es un secreto y no da acceso a la cuenta, así que puede ir en el código del cliente.
- La información del negocio con la que responde el asistente: servicios y precios, preguntas frecuentes, políticas, horarios y zonas de servicio. Lo más rápido es escribir la dirección del sitio y dejar que Nexoply importe las páginas públicas, incluidas las páginas hechas con JavaScript, así que un sitio en React también funciona. No se agrega nada hasta que se aprueba.
Opción 1: Agrega el script a index.html (recomendado)
Toda SPA de React tiene un HTML base. En Vite es index.html en la raíz del proyecto; en Create React App es public/index.html. Pega el código justo antes de la etiqueta de cierre </body>:
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<!-- Chatbot con IA de Nexoply -->
<script src="https://nexoply.com/widget.js" data-chatbot="YOUR-KEY" async></script>
</body>Reemplaza YOUR-KEY por la clave de la página Chatbot. El script carga de forma asíncrona, así que nunca bloquea el renderizado de tu app. Agrega data-open="true" a la etiqueta si quieres que la ventana de chat se abra al cargar. Esa es toda la instalación: compila, despliega y el botón aparece en todas las rutas.
Opción 2: Cárgalo desde un componente con useEffect
Cárgalo desde el código cuando quieras controlar cuándo aparece, por ejemplo solo después de que el visitante acepte tu aviso de cookies, o para tener la clave en una variable de entorno por despliegue. En Vite, pon VITE_NEXOPLY_KEY=tu-clave en un archivo .env y agrega esto a tu componente raíz:
// src/App.tsx
import { useEffect } from "react";
const NEXOPLY_KEY: string = import.meta.env.VITE_NEXOPLY_KEY;
export default function App() {
useEffect(() => {
// ¿Ya está en la página? No hay nada que hacer.
if (document.querySelector("script[data-chatbot]")) return;
const s = document.createElement("script");
s.src = "https://nexoply.com/widget.js";
s.async = true;
s.dataset.chatbot = NEXOPLY_KEY;
document.body.appendChild(s);
}, []);
return <main>{/* tu app */}</main>;
}El widget lee su configuración de su propia etiqueta script, así que la etiqueta debe conservar el atributo data-chatbot y un src que contenga widget.js. Al asignar s.dataset.chatbot se crea ese atributo. Create React App no tiene import.meta.env: ahí usa process.env.REACT_APP_NEXOPLY_KEY.
- Por qué no hay función de limpieza. El widget no tiene una API para quitarlo una vez cargado, y vive fuera de tu árbol de React, así que desmontar App no necesita deshacer nada. Deja este efecto en el componente raíz, que sigue montado durante toda la visita.
- Por qué StrictMode no es un problema. En desarrollo, React StrictMode ejecuta los efectos dos veces. La comprobación con querySelector omite la segunda ejecución, y aunque el script se agregara dos veces, el widget se monta una sola vez por clave de chatbot. Por la misma razón, la recarga en caliente también es segura.
Cómo se comporta en una single-page app
- Queda fuera de tu árbol de React. El widget se monta en document.body, fuera de tu elemento #root, así que los re-renders y los cambios de ruta nunca lo quitan ni cambian su estilo.
- Shadow DOM en ambos sentidos. Tu CSS (Tailwind, CSS modules, resets globales) no se filtra al chat, y su CSS no se filtra a tu app.
- Los cambios de ruta funcionan solos. Con React Router o cualquier router basado en el historial, los visitantes conservan su conversación mientras navegan, y las reglas de página (como una pestaña lateral solo en /pricing) se vuelven a comprobar cuando cambia la URL. Sin código extra.
- Sin cookies. Guarda un identificador anónimo del visitante en localStorage y la conversación actual en sessionStorage.
Abre el chat desde tu propio botón
¿Quieres un botón "Chatea con nosotros" en la portada o en la página de precios? Dispara el evento nexoply:open-chat en window:
export function ChatButton() {
return (
<button onClick={() => window.dispatchEvent(new Event("nexoply:open-chat"))}>
Chatea con nosotros
</button>
);
}No necesita ningún import: el widget escucha este evento en window. Si prefieres mostrar solo tu propio botón, configura el botón de mensaje como "Sin botón" con una regla de página en el panel.
Pruebas locales y solución de problemas
Antes de desplegar, revisa estos tres puntos:
- Sitios permitidos. Si completaste Permitir solo en estos sitios web (panel → Chatbot), agrega tu host de desarrollo con su puerto, como localhost:5173 para Vite o localhost:3000 para Create React App, o deja la lista vacía mientras pruebas.
- Content-Security-Policy. Si tu app envía un encabezado o meta tag de CSP, permite https://nexoply.com en script-src, connect-src e img-src.
- Pruébalo de punta a punta. Ejecuta la app, haz clic en el botón de chat, haz una pregunta real y búscala en Conversaciones en el panel.
Si el botón sigue sin aparecer:
- Clave vacía. Muestra NEXOPLY_KEY en la consola. Vite solo expone las variables que empiezan con VITE_, y tienes que reiniciar el servidor de desarrollo después de editar .env.
- Solicitud bloqueada. Mira la consola y la pestaña Network del navegador en busca de errores de CSP o de un widget.js bloqueado.
- Chatbot apagado. Comprueba que el interruptor Chatbot activado esté encendido.
- Bloqueadores de anuncios. En casos raros, una extensión del navegador bloquea los widgets de chat. Prueba en una ventana privada sin extensiones.
Próximos pasos: personalízalo sin volver a desplegar
Una vez que el script está puesto, no tienes que volver a tocar el código: los cambios hechos en el panel llegan al sitio en aproximadamente un minuto. En Chatbot → Personalizar puedes darle estilo al botón de mensaje (ícono o tu propia imagen o SVG, texto, forma, tamaño, colores, posición) o usar en su lugar una pestaña lateral en el borde de la pantalla. Define un aspecto distinto en celulares y usa reglas de página para cambiarlo en rutas concretas (por ejemplo /pricing, o /servicios/*). La ventana de chat usa tus fuentes, colores y logo, y la pantalla de inicio puede ofrecer botones como Reservar, Llamar o WhatsApp.
¿Usas otro framework? Mira la guía de Next.js o la guía de Vue. Para el panorama completo, lee cómo funciona o compara los planes.
Preguntas frecuentes
¿Hay un paquete npm o un componente de React?
No, y no lo necesitas. El widget es siempre el script https://nexoply.com/widget.js con un atributo data-chatbot. Agrégalo en index.html o desde un useEffect; toda la configuración está en el panel.
¿Funciona con React Router?
Sí. El widget conserva la conversación mientras los visitantes navegan del lado del cliente y vuelve a comprobar las reglas de página cuando cambia la URL, sin código extra. Vive fuera de tu árbol de React, así que los cambios de ruta nunca lo quitan.
¿Hará más lenta mi app?
No de forma apreciable. El script carga de forma asíncrona y nunca bloquea el renderizado, y funciona dentro de su propio Shadow DOM sin tocar tus componentes.
¿Funciona con Next.js?
Sí, con el componente next/script en tu layout raíz. Mira la guía de Next.js para los fragmentos del App Router y del Pages Router.
¿Cómo lo oculto en algunas rutas?
No hay una API para quitarlo una vez cargado. En su lugar, agrega una regla de página con "Sin botón" (panel → Chatbot → Personalizar → Botón de mensaje → Distinto en algunas páginas), o apaga el chatbot.
