Convot Convot
Back to Security and Privacy
Security and Privacy

Identity Verification

How to use HMAC identity verification to cryptographically confirm that a visitor is who they claim to be.

Updated June 11, 2026

When your widget calls Convot.identify(...), it tells Convot who the current visitor is - their email, name, or external ID. Without verification, any visitor can claim to be any user.

Identity verification uses a server-signed HMAC hash to prove the claim came from your backend, not from the visitor’s browser.

How it works

  1. Your server computes HMAC-SHA256(identity_secret, <value_to_sign>) and passes the result to the widget as user_hash.
  2. When the widget sends the identify call to Convot, it includes the hash.
  3. Convot recomputes the expected hash server-side and compares it in constant time. If they match, the identity is verified.

The signed value is the external_id when you pass one, otherwise the email.

Finding your identity secret

  1. Go to Settings → Apps → [your app] → Setup.
  2. Your identity secret is shown in the security section. It’s a 64-character hex string.
ℹ️

Treat the identity secret like a password. Never put it in client-side code or commit it to a public repo. It lives on your server only.

Computing the hash

Ruby

require "openssl"
hash = OpenSSL::HMAC.hexdigest("SHA256", identity_secret, user_email)

Node.js

const crypto = require("crypto");
const hash = crypto
  .createHmac("sha256", identitySecret)
  .update(userEmail)
  .digest("hex");

Python

import hmac, hashlib
hash = hmac.new(
  identity_secret.encode(),
  user_email.encode(),
  hashlib.sha256
).hexdigest()

Replace user_email with external_id if you use an external ID to identify visitors.

Passing the hash to the widget

Convot.identify({
  email: "[email protected]",
  name: "John Smith",
  user_hash: "<hash computed on your server>"
});

Signing the Shopify shop domain

If you want the Shopify merchant revenue sidebar to appear in conversations, you also need to sign the shop field separately:

Convot.identify({
  external_id: "johns-store.myshopify.com",
  email: "[email protected]",
  shop: "johns-store.myshopify.com",
  shop_hash: "<HMAC-SHA256 of shop value using your identity_secret>"
});

The shop_hash is checked independently from user_hash. Both use the same identity secret. An unsigned shop value is silently ignored - no merchant revenue data is attached unless the signature is valid.

Enforcing verification (rejecting unverified sessions)

By default, Convot accepts identity calls with or without a valid hash - it just treats unsigned ones as lower-trust. If you want to enforce strict verification so that any widget session without a valid hash is rejected, turn on Require identity verification in Settings → Apps → [your app] → Security.

⚠️



Enabling this will break any identify calls that don’t include a valid user_hash. Test in development before enabling in production.

Rotating the identity secret

If your identity secret is ever exposed, rotate it immediately:

  1. Go to Settings → Apps → [your app] → Setup.
  2. Click Regenerate identity secret.
  3. Update the secret on your server and redeploy.

Old sessions signed with the previous secret will fail verification after the rotation.

Was this article helpful?