React y Next.js
Monta el loader público una sola vez en un layout de React o Next.js que controles y límpialo de forma deliberada.
Monta el loader público una sola vez en un layout de React o Next.js que controles y límpialo de forma deliberada.
Prepara los orígenes y el alcance#
Activa Mostrarlo en mi sitio web para el agente (página del agente → Ponlo en marcha → Widget para sitio web) y añade los orígenes exactos de local, vista previa y producción en Direcciones de sitio web permitidas. Decide si el lanzador debe mantenerse en todas las navegaciones del cliente (layout raíz) o existir solo en rutas concretas (layout o componente anidado).
Next.js App Router#
Usa next/script en un componente que renderice el layout propietario del lanzador. El slug es seguro de exponer; no uses una clave de API ni una variable de entorno secreta.
import Script from "next/script";
export function AgentEmbed() {
return (
<Script
id="maf-agent"
src="https://makeagent.fast/embed.js?v=20261022-open"
strategy="afterInteractive"
data-agent="YOUR_SITE_SLUG"
data-position="right"
data-label="Ask us"
/>
);
}Renderiza <AgentEmbed /> una sola vez en app/layout.tsx para un agente en todo el sitio, o en un layout anidado para un grupo de rutas. No renderices una copia independiente desde cada componente de página. afterInteractive evita el acceso al DOM desde el servidor y no bloquea el análisis inicial del HTML.
En el Pages Router de Next.js, renderiza el mismo componente una sola vez desde pages/_app.tsx para que funcione en todo el sitio. Renderizarlo desde una página individual solo es apropiado cuando salir de esa página deba eliminar el agente; en ese caso usa el patrón explícito de efecto/limpieza que se muestra más abajo, porque un script externo ya cargado ha creado DOM fuera del árbol de React.
React sin Next.js#
Crea el script dentro de un efecto. Un ID de script estable evita la inserción duplicada con el Strict Mode de desarrollo. Si el componente está limitado a una ruta, la limpieza debe eliminar tanto el script como la raíz creada por el loader.
import { useEffect } from "react";
const slug = "YOUR_SITE_SLUG";
export function AgentEmbed() {
useEffect(() => {
if (document.getElementById(`maf-embed-root-${slug}`)) return;
const script = document.createElement("script");
script.id = "maf-agent";
script.src = "https://makeagent.fast/embed.js?v=20261022-open";
script.dataset.agent = slug;
script.dataset.position = "right";
script.async = true;
document.body.appendChild(script);
return () => {
script.remove();
document.getElementById(`maf-embed-root-${slug}`)?.remove();
};
}, []);
return null;
}Para un lanzador en todo el sitio, monta este componente por encima del router y omite el desmontaje según la ruta. Conservar la raíz mantiene el iframe y la conversación durante la navegación.
Configuración del entorno#
Una variable pública de tiempo de compilación puede contener el slug, ya que no es secreto. Valídalo antes de renderizar y mantén las claves de API de MAF y las credenciales de proveedores reales solo en el servidor. Si falta el slug, el loader muestra una advertencia y termina en lugar de crear un lanzador.
Si tu aplicación sirve a distintos clientes (tenants) desde una misma compilación de React, no cambies data-agent en un script que ya se ha ejecutado. Asigna al tenant actual un único slug estable, elimina la raíz del slug anterior durante un cambio de tenant autenticado y después monta un script nuevo. Nunca permitas que un parámetro de consulta no confiable elija un slug de otro tenant.
Verifica la hidratación y la navegación#
- Carga directamente una ruta pública y confirma que hay un solo lanzador.
- Navega en el cliente por las rutas que deben conservarlo.
- En una instalación anidada o limitada a rutas, sal de la ruta y confirma que desaparecen tanto el script como la raíz; luego vuelve y confirma que aparece un único lanzador nuevo.
- Inspecciona Network/CSP y prueba un mensaje real.
- Ejecuta la compilación de producción; el Strict Mode de desarrollo por sí solo no refleja el comportamiento final.
Solución de problemas#
| Síntoma | Solución |
|---|---|
document is not defined | El código del DOM se ejecutó durante el SSR; muévelo a useEffect o usa next/script |
| Aparecen dos lanzadores/agentes | Hay varios slugs o componentes montados; mantén un único layout propietario |
| El lanzador permanece tras salir de la ruta | Elimina maf-embed-root-SLUG en la limpieza, no solo el script |
| El lanzador desaparece en cada navegación | Móntalo más arriba en el árbol del layout o del router |
| Funciona en local pero no en vista previa/producción | Añade a la lista de permitidos el origen exacto de cada despliegue |
Actualmente no se publica ningún adaptador de React/Next en npm; estos ejemplos usan el loader público compatible, independiente de la API REST.