Chat widget
One script tag, ~12 KB gzipped, no dependencies. Drops into any HTML page and starts collecting messages immediately.
Install
Drop this snippet anywhere inside the <body>:
<script async src="https://leadiosa.com/widget.js" data-workspace="YOUR_WORKSPACE_ID"> </script>
The script loads asynchronously, mounts a launcher button in the bottom-right corner, and connects to our real-time backend the first time the visitor opens it (or the first time we have something to push them).
Data attributes
Configure the widget by adding data-* attributes to the install script:
| Attribute | Type | Default | Description |
|---|---|---|---|
data-workspace | string | — | Required. Your workspace ID from Settings. |
data-language | string | auto | One of en, es, de, fr, it, pt, ru, uk. "auto" picks from navigator.language. |
data-position | string | right | Either "left" or "right" — which side the launcher pins to. |
data-theme | string | auto | Either "light", "dark", or "auto" (follows prefers-color-scheme). |
data-open-on-load | boolean | false | Open the chat panel automatically on first load. Use sparingly. |
data-offset-bottom | number | 20 | Pixels from the bottom edge, to clear cookie banners or other floating UI. |
Identifying visitors
For authenticated visitors — users already signed in to your product — you can pre-populate their identity so the conversation isn't anonymous. Call leadiosa.identify(...) any time after the script tag has loaded:
leadiosa.identify({
id: "user_8f3c12", // your stable user id
email: "alex@acme.example", // optional
name: "Alex Hope", // optional
attributes: {
plan: "pro",
company: "Acme Co.",
signed_up_at: "2025-08-14" // any JSON-serialisable value
}
});Subsequent visits with the same id rejoin the same conversation. Attributes are surfaced to the operator in the conversation sidebar.
HMAC-signed identity (anti-spoofing)
To prevent a malicious user from masquerading as someone else, compute an HMAC on your server and pass it alongside the identify call:
// On your server, with a secret stored in env:
const hmac = crypto.createHmac("sha256", process.env.LEADIOSA_SECRET)
.update(userId)
.digest("hex");
// Send hmac to the browser, then:
leadiosa.identify({
id: userId,
email: userEmail,
hmac: hmac
});Once HMAC verification is enabled on the workspace, identify calls without a valid signature are rejected.
JavaScript API
The widget exposes a small set of methods on the global leadiosa object once it has loaded.
| Method | Description |
|---|---|
leadiosa.open() | Opens the chat panel programmatically. |
leadiosa.close() | Closes the chat panel. |
leadiosa.toggle() | Toggles open/closed. |
leadiosa.hide() | Hides the launcher button entirely. Use on pages where chat is not appropriate. |
leadiosa.show() | Restores the launcher. |
leadiosa.logout() | Clears the visitor session. Call when your user signs out so the next user gets a fresh session. |
leadiosa.setLanguage(code) | Change UI language at runtime. |
Events
Subscribe to widget events to track engagement in your own analytics:
leadiosa.on("chat:opened", () => {
analytics.track("Chat opened");
});
leadiosa.on("message:sent", ({ text }) => {
analytics.track("Chat message sent", { length: text.length });
});
leadiosa.on("message:received", ({ from }) => {
analytics.track("Chat reply received", { from });
// "from" is "operator" | "agent" (AI)
});
leadiosa.on("chat:closed", () => {
analytics.track("Chat closed");
});Styling
The widget renders inside a shadow DOM so host-page CSS never accidentally bleeds in. You can still override its accent colour from workspace settings, or supply a small custom CSS block:
leadiosa.setStyles({
accent: "#5e3bff",
radius: 12, // launcher and panel corner radius (px)
launcherIcon: "chat" // "chat" | "headset" | "bolt"
});Privacy and consent
When a visitor sends a message, you (the workspace operator) become the data controller for that message under GDPR — see our GDPR page for the full breakdown.
We recommend mentioning live chat in your privacy notice, and (if your cookie banner gates non-essential scripts) only loading widget.js after the visitor opts in.