User Identification
User identification lets you associate messenger conversations with known users in your application.
Anonymous visitors
Section titled “Anonymous visitors”For visitors who aren’t logged in, set the user to anonymous:
optlo.setUser({ id: null });Anonymous sessions are tracked via browser cookies.
Identified users (without verification)
Section titled “Identified users (without verification)”Pass user data directly when JWT verification is not required:
optlo.setUser({ id: "user-123", email: "jane@example.com", name: "Jane Doe", avatarUrl: "https://example.com/avatar.jpg", attrs: { plan: "pro", active: true, },});User data fields
Section titled “User data fields”| Field | Type | Required | Description |
|---|---|---|---|
id |
string | number | null | yes | Unique user ID, or null for anonymous |
email |
string | no | Email address |
name |
string | no | Display name |
avatarUrl |
string | no | Profile image URL (must be https://) |
attrs |
object | no | Custom key-value pairs (max 50) |
organizations |
array | no | Organizations the user belongs to (max 10) |
User and organization data appears in the user details panel in the inbox.
Organization fields
Section titled “Organization fields”Each entry in the organizations array accepts the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | number | yes | Unique organization identifier |
name |
string | yes | Organization display name |
attrs |
object | no | Custom key-value pairs (max 50) |
Organizations are stored for identified users (a non-null id), with or without a signed JWT. Anonymous updates ignore the organizations array.
Organizations are deduplicated by their id. A user can belong to up to 10 organizations.
For identified users, the organizations array is treated as the complete list. Omitting an organization from a subsequent update removes that membership; omitting the array clears all memberships.
Identified users (with verification)
Section titled “Identified users (with verification)”Identity verification uses asymmetric cryptography — you sign user data on your server and we verify it on ours. This ensures user identity can’t be faked from the browser. See Settings > Messenger > Install for a full walkthrough.
optlo.setUser({ jwt: "eyJ..." });Generating the JWT
Section titled “Generating the JWT”On WordPress, the Optlo plugin does this for you: turn on Identify signed-in users and it creates the key pair, registers the public key, and signs a token for each signed-in user.
-
Generate an asymmetric key pair using one of the supported algorithms:
EdDSA,ES256,PS256, orRS256. You can useopensslto generate a key pair:Terminal window openssl genpkey -algorithm ed25519 -out private.pemopenssl pkey -in private.pem -pubout -out public.pem -
Upload the public key (SPKI format) in the dashboard.
-
Sign a JWT on your server with the private key:
import { SignJWT } from "jose";let jwt = await new SignJWT({id: "user-123",email: "jane@example.com",name: "Jane Doe",}).setProtectedHeader({ alg: "EdDSA" }).setExpirationTime("5m").sign(privateKey); -
Pass the signed JWT to the widget from your frontend.
The JWT payload uses the same user data fields as the unsigned setUser call. The exp claim is required. You can optionally include a jti claim for one-time-use token enforcement.
When replacing a public key, the previous key remains valid for 2 hours to prevent disruption.
Attributes in workflows
Section titled “Attributes in workflows”Signed and unsigned setUser calls replace attrs; omitting attrs clears them. Organization updates follow the same rules for signed and unsigned identified users. Attribute names are configurable: for example, a billing integration can use billingAccount without requiring a field named stripeCustomerId.
Unsigned identification is intended for testing. Require verification of website users in production before relying on attributes or organization memberships for authorization or billing, and check that the workflow session is verified.
Workflows load the latest profile when they start or resume. Attribute and membership changes do not cancel running work; its context remains the snapshot loaded for that execution. The session is checked once when the workflow starts; a verified pause can only be resumed by a verified session. Billing actions derive customer IDs from attributes and reject conflicting supplied IDs.