Yak Docs
Customization

End-user identity

Pass a signed user identity into the widget and Yak will persist conversations against that user. When the same user returns, the widget shows a history pane so they can resume a previous chat or start a new one.

This is opt-in. If you don't pass a user, the widget behaves exactly as it always has — conversations live only in the browser and nothing is persisted server-side.

How it works

  1. Your backend signs the user id with your application's API secret using HMAC-SHA256.
  2. The signed identity is passed to <YakProvider> in the browser.
  3. The widget forwards { id, hash } to Yak on every request that touches that user's data.
  4. Yak verifies the hash against the secret, upserts the end-user record, and persists messages against a conversation owned by that user.

The secret never leaves your server. The hash proves the browser is acting on behalf of a real account from your system — without it, anyone with an end-user's id could impersonate them.

This is the same identity-verification model used by Intercom and similar widget vendors. Only the user id is signed, so the identity is tamper-proof.

Set it up

Grab your API secret

Open your application's security settings and reveal the End-user identity card. Copy the secret somewhere safe — treat it like any other backend credential.

Store it as an environment variable on your server (never expose it to the browser):

YAK_API_SECRET=...

Sign the user id on your server

Compute an HMAC-SHA256 hex digest of the user id using the secret:

import crypto from "node:crypto";

const userHash = crypto
  .createHmac("sha256", process.env.YAK_API_SECRET!)
  .update(currentUser.id)
  .digest("hex");
import hmac, hashlib, os

user_hash = hmac.new(
    os.environ["YAK_API_SECRET"].encode(),
    current_user.id.encode(),
    hashlib.sha256,
).hexdigest()
require "openssl"

user_hash = OpenSSL::HMAC.hexdigest(
  "SHA256",
  ENV["YAK_API_SECRET"],
  current_user.id,
)
import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "os"
)

mac := hmac.New(sha256.New, []byte(os.Getenv("YAK_API_SECRET")))
mac.Write([]byte(currentUser.ID))
userHash := hex.EncodeToString(mac.Sum(nil))

Send the hash to the browser however you already pass user data (server-rendered HTML, a session API, etc.).

Pass the identity into the widget

Add the user prop to <YakProvider>:

import { YakProvider } from "@yak-io/react";

<YakProvider
  appId={process.env.NEXT_PUBLIC_YAK_APP_ID!}
  user={{
    id: currentUser.id,
    hash: currentUser.yakHash, // from your server
  }}
>
  {children}
</YakProvider>

That's it. Open the widget and you'll see a new history icon in the header — click it to browse past conversations or start a new one.

The user prop

FieldTypeRequiredDescription
idstringYesStable user id from your system. HMAC-protected.
hashstringYesHex HMAC-SHA256 of id signed with your application's API secret.

What the end-user sees

When user is set and the hash verifies:

  • A clock icon appears in the chat header.
  • Clicking it opens a slide-over panel listing recent conversations, newest first.
  • Selecting a conversation re-hydrates the chat with the persisted messages — the user can keep talking right where they left off.
  • A "New" button starts a fresh conversation without losing the old ones.
  • Each conversation has a trash icon for removing it (and its messages) permanently.

When user is not set, none of this UI shows and no data is persisted.

Anonymous mode

If you don't pass user, the widget works exactly as before:

  • Conversations live only in the browser.
  • Nothing is written to Yak's database against an identifiable user.
  • The history pane is hidden.

You can mix the two modes inside the same application — for example, anonymous chat on a public marketing page and signed-in chat in your dashboard.

Rotating the secret

If you suspect the secret has leaked, rotate it from the dashboard. Rotation invalidates every previously signed hash, so deployed integrations will fail until you re-deploy with the new value. Plan the rotation alongside a deploy of your server code.

Security model

  • What's signed: only the user id. A holder of the secret can produce a valid identity for any user id, so keep the secret on the server.
  • Where verification happens: every Yak endpoint that touches user data (/api/chat when user is present, and the conversation history endpoints) re-verifies the hash and the user's ownership of the conversation. There are no session cookies — the signed identity rides along on each request.

For the broader security context, see the Security page.

On this page