Widget

Identifying users

Tag conversations with the signed-in user's identity so the agent knows who's asking — and your team has the context.

Why identify

Without identify, every conversation is anonymous. The agent can answer questions, but it can't personalize — it doesn't know the user's plan, workspace, or history. With identify, the agent can:

  • Pull user-specific account info from your knowledge sources.
  • Quote prior threads ("you reported a similar issue last month — has it changed?").
  • Skip onboarding questions for paid users ("I see you're on Pro…").
  • Route to the right team via the dashboard inbox.

Basic identify (development)

For local development and quick prototyping:

js
window.DuggAI.identify({
  id: "u_abc123",
  email: "alice@example.com",
  traits: { name: "Alice Smith", plan: "pro" },
});
Not safe for production
Anyone can spoof this from the browser console — they could pose as another user and read their conversation history. For production, sign the user id on your server with HMAC (below) and pass the result as hash.

HMAC-signed identify (production)

Signed identify uses two values from Dashboard → Integrations— your public key and your org's signing secret. If you don't see a signing secret yet, email support@duggai.com to turn signed identify on for your org.

  • Public key (duggsupp_pk_…) — goes in your install snippet.
  • Signing secret — stays on your server and is used to sign the user id.

1. Server: compute the hash

ts
// Node.js (e.g. /api/duggai-identity route in Next.js)
import crypto from "node:crypto";

export function hashUserId(userId: string) {
  return crypto
    .createHmac("sha256", process.env.DUGGAI_SIGNING_SECRET!)
    .update(userId)
    .digest("hex");
}

2. Send the hash to the browser

Either inline it during SSR (server component, hydration data) or fetch it from an authenticated endpoint. Whatever fits your auth flow. The hash itself is opaque — leaking it only lets someone impersonate that one user, which they already are.

3. Browser: identify with the hash

js
window.DuggAI.identify({
  id: "u_abc123",                 // must match the id you HMAC'd
  hash: hashFromServer,           // HMAC-SHA256(secret, id) as hex
  email: "alice@example.com",
  traits: { name: "Alice Smith", plan: "pro" },
});

On every chat request, the widget sends the hash via the X-DuggAI-User-Hash header (legacy X-DuggSupport-User-Hashis still accepted). Our backend re-computes HMAC-SHA256(secret, id); if they match, the conversation is bound to that user and shown in the dashboard as verified. If they don't match, the message is treated as anonymous (unverified).

Custom traits

Pass any extra fields via traits. Strings, numbers, booleans only — no nested objects. The agent gets these as context on every reply.

js
window.DuggAI.identify({
  id: "u_abc123",
  hash: hashFromServer,
  email: "alice@example.com",
  traits: {
    name: "Alice Smith",
    plan: "pro",
    workspaceId: "ws_42",
    signupDate: "2025-04-12",
    trialDaysLeft: 5,
  },
});

Updating identity

Call identify() again with new values to update. Useful when a user upgrades plans or switches workspaces mid-session.

Logging out

When your user signs out, call window.DuggAI.identify() with no argument to clear the stored identity. The next message starts a fresh, anonymous session.