Identity verification makes sure the person writing in your chat is really the logged-in user they claim to be. Customerly verifies users with an email hash: an HMAC-SHA256 of the user's email, signed with a secret only your server knows.
Step 1: get your verification secret
Contact support via chat to get your verification secret key. Store it as a server-side secret (for example CUSTOMERLY_IDENTITY_SECRET in your server environment or Supabase secrets). Never put it in client code, in a NEXT_PUBLIC_ or VITE_ variable, or in your repository.
Step 2: generate the hash on your server
Lower-case the email before hashing. Generate the hash only for the user who is logged in.
Node.js / Next.js (server component, route handler or API route)
import crypto from "node:crypto";
export function customerlyEmailHash(email: string) {
return crypto
.createHmac("sha256", process.env.CUSTOMERLY_IDENTITY_SECRET!)
.update(email.toLowerCase())
.digest("hex");
}Supabase Edge Function (Deno)
import { createClient } from "jsr:@supabase/supabase-js@2";
Deno.serve(async (req) => {
const supabase = createClient(
Deno.env.get("SUPABASE_URL")!,
Deno.env.get("SUPABASE_ANON_KEY")!,
{ global: { headers: { Authorization: req.headers.get("Authorization")! } } }
);
const { data: { user } } = await supabase.auth.getUser();
if (!user?.email) return new Response("Unauthorized", { status: 401 });
const key = await crypto.subtle.importKey(
"raw",
new TextEncoder().encode(Deno.env.get("CUSTOMERLY_IDENTITY_SECRET")!),
{ name: "HMAC", hash: "SHA-256" },
false,
["sign"]
);
const sig = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(user.email.toLowerCase()));
const email_hash = Array.from(new Uint8Array(sig)).map((b) => b.toString(16).padStart(2, "0")).join("");
return Response.json({ email_hash });
});Python
import hmac, hashlib, os
def customerly_email_hash(email: str) -> str:
secret = os.environ["CUSTOMERLY_IDENTITY_SECRET"].encode()
return hmac.new(secret, email.lower().encode(), hashlib.sha256).hexdigest()PHP
hash_hmac("sha256", strtolower($email), $secret);Step 3: pass the hash to the live chat
Add email_hash next to the email in load() or update().
customerly.load({
app_id: "ADD YOUR PROJECT ID",
user_id: "REPLACE WITH YOUR USER ID",
name: "REPLACE WITH USER NAME",
email: "REPLACE WITH USER EMAIL",
email_hash: "HASH FROM YOUR SERVER"
});React and Next.js (react-live-chat-customerly): update({ user_id, email, email_hash, name, attributes }). See Install Customerly in React and Next.js.
Step 4: turn verification on, in this order
Deploy the code that sends
email_hashfor every logged-in user.Check a few conversations from logged-in users: they arrive with the right user information.
Only then ask support to enable Identity Verification.
⚠️ Once Identity Verification is enabled, users without a valid email_hash can no longer authenticate in the chat.
Verify that it works
Start a new conversation as a logged-in, verified user and check in your inbox that it arrived with the right name, email and attributes.
