Install
Layout Modes
Set layout in Dashboard -> Widgets -> Appearance -> Layout, or passlayout in the script.
bubble: Default floating launcher bubble.tab: Vertical side tab launcher.- If
layoutis not provided, it defaults tobubble.
Constructor Options
widgetToken(required): Widget token from Dashboard.layout(optional):bubbleortab(default:bubble).bottomSpacing(optional): Distance in pixels from the page bottom (default:28).
Bottom Spacing Example
JavaScript API
After creating a widget instance, you can control it programmatically:widget.init(): Initialize the widget and load config from your widget token.widget.open(): Open chat UI (also makes a hidden widget visible).widget.close(): Close chat UI.widget.toggle(): Toggle between open and closed.widget.show(): Show widget UI if hidden.widget.hide(): Hide widget UI.widget.identify(params): Identify a logged-in user and link chat activity to their contact.widget.resetIdentity(): Clear the stored identity (for example, on logout).widget.destroy(): Remove widget DOM and event listeners.
Identify Logged-In Users
Useidentify() when a visitor is signed into your product. Simple links widget conversations and activity to that contact so agents and teammates see the right person.
Without identity verification
If identity verification is not enabled on your widget, you can identify users with just their ID and optional profile fields:identify() can be called before or after init(). If you call it early, the widget queues the request and sends it once initialization finishes.
Identify parameters
Conversation linkage
Onceidentify() has resolved, every new conversation the visitor starts is linked to that contact. Conversations that are already open are not re-linked: the contact is attached when the conversation is created and stays fixed for its lifetime.
While an identify() request is being verified, the widget briefly pauses conversation loading and sending. This prevents a previously stored user identity from being used during an account switch. If verification fails, the previous identity remains cleared and the widget continues anonymously.
When a linked conversation is created, its contact is set and the agent’s template parameters are populated from the contact record as stored on Simple’s side, never directly from the values you passed to identify():
The
contact object is always present on a linked conversation and each field is null when unknown. On an anonymous chat, {{contact}} itself is null. Simple owns this object: values passed in context, and updates made by the agent’s own extraction steps, never overwrite it.
Simple also sets the flat working values {{email}}, {{name}}, {{phone_number}} and {{external_id}}, but only when the contact has a value for them. These are the parameters existing agents typically reference, and the agent’s own extraction steps may update them later in the conversation, so use {{contact.*}} when you need the verified value.
Parameter precedence, lowest to highest: widget default params, then context passed from the page, then the verified contact.
If the contact cannot be resolved for the widget’s organization, the conversation is created anonymously and a warning is logged on Simple’s side; chat keeps working.
Calling resetIdentity(), or identifying as a different user, discards the conversation stored in the visitor’s browser that was created under the previous identity, so the next message starts a fresh, correctly attributed conversation. Conversations started anonymously are kept.
Authenticated Identity with HMAC
For production apps, enable identity verification so visitors cannot spoof another user’s identity from the browser. When identity verification is enabled on a widget, everyidentify() call must include a valid HMAC. Simple rejects identify requests that omit the HMAC or pass an invalid signature.
How it works
- Your backend signs the user’s ID with your widget identity verification secret.
- Your frontend receives that HMAC from your backend (for example, as part of the session payload).
- Your page calls
widget.identify({ id, hmac, ... }). - Simple verifies the HMAC before accepting the identity.
Get your widget secret
Each widget has its own identity verification secret. In the Simple dashboard, open Widgets, select the widget, and go to Install → Identity verification. Choose Reveal, then copy the secret into your backend’s environment variables or secrets manager. Identity verification is off by default. Finish sending HMACs from your backend before turning on Require verified identities and saving the widget; otherwise, unsignedidentify() calls will be rejected.
Generate the HMAC on your server
The HMAC is HMAC-SHA256 of the userid, using your identity verification secret as the key. The digest must be hex-encoded.
Node.js
Python
Ruby
id string you pass to identify().
Pass the HMAC to the widget
Recommended end-to-end flow
- Reveal the widget’s identity verification secret in Install → Identity verification and store it on your backend.
- Your backend loads the signed-in user and generates
hmac = HMAC-SHA256(user.id, secret). - Your page renders (or fetches)
id, profile fields, andhmac. - Initialize the widget and call
identify()with those values. - Confirm every authenticated
identify()call includes a valid HMAC, then enable Require verified identities and save the widget. - On logout, call
resetIdentity(). Besides clearing the stored identity, this discards the conversation the browser had open under that user, so the next person on a shared device cannot pick up their chat.
Security notes
- Sign only the user
id(not email/name/phone). Profile fields are traits; the HMAC authenticates identity. - Keep the identity verification secret server-side only (environment variable or secrets manager).
- Secrets are unique per widget. An HMAC generated with one widget’s secret cannot authenticate a user on another widget.
- If a secret is exposed, disable identity verification for that widget and contact Simple support to replace it before re-enabling verification.
- If identity verification is enabled and the HMAC is missing or invalid, identify fails and the visitor stays anonymous.