Priority Hunter
/Docs/Widget/Frameworks/Next.js
DocsWidgetFrameworksNext.js

Next.js (App Router)

Como window solo está disponible en el cliente, el cargador del widget debe ser un Client Component montado en el layout raíz.

El componente cargador

components/WidgetLoader.tsx
// components/WidgetLoader.tsx
'use client';

import { useEffect } from 'react';
import { useSession } from 'next-auth/react';

export function WidgetLoader() {
  const { data: session } = useSession();

  useEffect(() => {
    if (window.self !== window.top) return; // skip inside iframes
    if (document.getElementById('ph-embed-script')) return;

    if (!(window as any).PH) {
      (window as any).PH = function(...args: unknown[]) {
        ((window as any).PH.q = (window as any).PH.q ?? []).push(args);
      };
    }

    (window as any).PH('init', { widgetId: process.env.NEXT_PUBLIC_PH_WIDGET_ID });

    const script = document.createElement('script');
    script.id = 'ph-embed-script';
    script.src = '/embed.js';     // if self-hosting, or the CDN URL
    script.async = true;
    document.head.appendChild(script);
  }, []);

  useEffect(() => {
    const user = session?.user;
    if (user?.email) {
      (window as any).PH?.('identify', {
        id:    user.id ?? user.email,
        email: user.email,
        name:  user.name ?? undefined,
      });
    } else {
      (window as any).PH?.('unidentify');
    }
  }, [session]);

  return null;
}
app/layout.tsx
// app/layout.tsx
import { WidgetLoader } from '@/components/WidgetLoader';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <WidgetLoader />
      </body>
    </html>
  );
}

Si alojas el widget tú mismo (es decir, Priority Hunter es tu propio despliegue), establece src como /embed.js para servirlo desde el mismo origen y evitar problemas de CORS o CSP.

Siguiente: Vue 3 →

Documentación de Priority Hunterpriorityhunter.com →