Install
Next.js
Install Whazzup in the app router with server-side identity.
Root loader
Use the Script component in the root layout. Always sign user identities on the server.
import Script from "next/script";
<Script
src="https://whazzup.io/widget.js"
data-workspace="YOUR_WORKSPACE_KEY"
strategy="afterInteractive"
/>Identity route
1. Install with user data — app/WhazzupWidget.tsx
One component publishes the signed-in person and loads the widget. Call logout explicitly when the person signs out.
"use client";
import Script from "next/script";
import { useEffect } from "react";
type User = { id: string; name: string; email: string } | null;
export function WhazzupWidget({ user }: { user: User }) {
useEffect(() => {
window.whazzupSettings = user
? { name: user.name, email: user.email, userId: user.id }
: null;
if (!user) window.whazzup?.("logout");
}, [user]);
return <Script src="https://whazzup.io/widget.js" data-workspace="YOUR_WORKSPACE_KEY" strategy="afterInteractive" />;
}2. Verified identity (recommended) — app/api/whazzup-identity/route.ts
Keep WHAZZUP_IDENTITY_SECRET in your server environment. Return a fresh, single-use token for the current signed-in user. Tokens expire after 5 minutes — call this endpoint on every full page load and whenever the token may have expired, never cache it.
import { createHmac, randomUUID } from "node:crypto";
import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
export async function GET() {
const session = await auth();
if (!session?.user?.id) return new NextResponse("Unauthorized", { status: 401 });
const payload = {
aud: "YOUR_WORKSPACE_KEY",
sub: session.user.id,
exp: Math.floor(Date.now() / 1000) + 300,
jti: randomUUID(),
name: session.user.name,
email: session.user.email,
attributes: {}
};
const body = Buffer.from(JSON.stringify(payload)).toString("base64url");
const signature = createHmac("sha256", process.env.WHAZZUP_IDENTITY_SECRET!)
.update(body).digest("base64url");
return NextResponse.json({ token: body + "." + signature });
}3. Browser — pass the signed token
Load the widget once, then identify after login. Without the token the person stays marked as unverified, even though name and email arrive. In a multi-page app, fetch and pass a fresh token on every page load; in a SPA, refetch after the token expires (5 minutes). Detach identity without destroying the session on sign-out.
"use client";
import Script from "next/script";
import { useEffect } from "react";
declare global { interface Window { whazzup: (...args: unknown[]) => void } }
export function WhazzupWidget({ signedIn }: { signedIn: boolean }) {
const identify = () => fetch("/api/whazzup-identity")
.then((response) => response.json())
.then(({ token }) => window.whazzup("identify", { token }));
useEffect(() => {
if (!signedIn) { window.whazzup?.("logout"); return; }
if (window.whazzup) void identify();
}, [signedIn]);
return <Script src="https://whazzup.io/widget.js" data-workspace="YOUR_WORKSPACE_KEY" strategy="afterInteractive" onLoad={() => { if (signedIn) void identify(); }} />;
}Client lifecycle
The client component fetches a token only after authentication and calls logout on sign-out. Keep the signing secret in the server environment.
