Identify logged-in users
Tell the agent who the signed-in visitor is, so it greets them by name, skips questions it already knows the answer to, and shows their details in your inbox.
When a visitor is already signed in to your website, your page can pass their name, email, and user ID to the chat widget. The agent then greets them naturally, stops asking for contact details it already has, and your inbox and contacts show who each conversation belongs to.
Identity comes in two trust levels:
- Unverified: your page simply passes the details. Anyone with browser developer tools could claim any name, so treat it as display-only.
- Verified: your server also sends a user hash, a signature computed with your secret key. Verified conversations show a Verified identity badge in your inbox, and only your server can produce the hash.
Pass identity from your page
If your pages are rendered per visitor on your server, add attributes to the embed script you already installed:
<script src="https://YOUR-DASHBOARD-HOST/widget.js"
data-chatbot-id="YOUR_AGENT_ID"
data-user-id="42"
data-user-name="Jane Doe"
data-user-email="[email protected]"
data-user-hash="HASH_FROM_YOUR_SERVER"
data-user-hash-issued-at="UNIX_SECONDS"
defer></script>Only use script attributes on pages generated freshly for each signed-in visitor. If your pages are cached or served by a CDN, one visitor's identity could be shown to another; use the JavaScript call instead.
Call identify whenever you know who the user is, before or after the
widget loads. This is the right choice for single-page apps and cached
sites:
<script>
window.FetchplyWidget = window.FetchplyWidget || { q: [] };
FetchplyWidget.q.push(["identify", {
userId: "42",
name: "Jane Doe",
email: "[email protected]",
attributes: { plan: "pro" },
userHash: "HASH_FROM_YOUR_SERVER",
issuedAt: 1764000000
}]);
</script>When the user signs out, call
FetchplyWidget.q.push(["logout"]) (or FetchplyWidget.logout() once the
widget has loaded). This also clears the visitor's saved conversations on
that device, which matters on shared computers.
You can also pass phone, avatarUrl, and up to 20 custom attributes
(lowercase keys like plan or signup_date). Attributes appear in the
conversation details panel in your inbox.
Verify identity with a user hash
Without verification, identity is a claim anyone can make. To prove it, your server signs the user ID and email with a secret only you and Fetchply know.
- In your dashboard, open Settings → Visitor identity and select Generate secret. Store it in your server environment; it is shown only once.
- On your server, compute the hash when rendering the page or in the API response your app already uses after sign-in:
const crypto = require("node:crypto");
const issuedAt = Math.floor(Date.now() / 1000);
const userHash = crypto
.createHmac("sha256", process.env.FETCHPLY_IDENTITY_SECRET)
.update(`${user.id}\n${user.email.toLowerCase()}\n${issuedAt}`)
.digest("hex");$issuedAt = time();
$payload = $user->id . "\n" . strtolower($user->email) . "\n" . $issuedAt;
$userHash = hash_hmac('sha256', $payload, getenv('FETCHPLY_IDENTITY_SECRET'));import hashlib, hmac, time
issued_at = int(time.time())
payload = f"{user.id}\n{user.email.lower()}\n{issued_at}"
user_hash = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest()issued_at = Time.now.to_i
payload = "#{user.id}\n#{user.email.downcase}\n#{issued_at}"
user_hash = OpenSSL::HMAC.hexdigest("sha256", ENV["FETCHPLY_IDENTITY_SECRET"], payload)- Pass
userHashandissuedAtalongside the identity. If you identify without an email, sign an empty string in its place.
A hash is valid for 24 hours from issuedAt, so compute it fresh when the
page or session is served, not once at signup.
Verification modes
In Settings → Visitor identity you can choose how strict the agent is:
- Optional (default): identity works with or without a hash; only hashed identities show the Verified badge.
- Required: identity without a valid hash is rejected. Turn this on once your site sends hashes everywhere.
- Off: identity from your website is ignored.
Rotating your secret
Selecting Rotate secret creates a new secret and keeps the old one working for 24 hours, so you can update your server without signing visitors out. Rotate immediately if you suspect the secret leaked.
Troubleshooting
- The agent still asks for the visitor's email. Identity attaches when the
visitor sends their first message. Confirm
identifyruns on the page (check for typos in the agent ID) and thatuserIdis present; identity without auserIdis ignored. - Conversations show "Unverified identity". The page passed identity
without a hash, or the hash did not match. Confirm your server signs
userId, the lowercased email, andissuedAtexactly as shown above, with the secret from this agent's settings. - Identity stopped working after rotating the secret. Hashes made with the old secret stop working 24 hours after rotation. Update the secret in your server environment and redeploy.
- Two people share one computer. Call
FetchplyWidget.q.push(["logout"])when a user signs out; it clears saved conversations on that device and starts a fresh session for the next person. If a different user signs in without a logout, the widget detects the switch and starts a fresh conversation automatically. - A visitor signed in mid-conversation as a different user. The widget starts a new conversation automatically so two people's messages are never mixed together.