Docs · Product

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>:

index.htmlhtml
<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).

Tip
The widget is a single ES module with no runtime dependencies. It will not conflict with React, Vue, htmx, or anything else running on the host page.

Data attributes

Configure the widget by adding data-* attributes to the install script:

AttributeTypeDefaultDescription
data-workspacestringRequired. Your workspace ID from Settings.
data-languagestringautoOne of en, es, de, fr, it, pt, ru, uk. "auto" picks from navigator.language.
data-positionstringrightEither "left" or "right" — which side the launcher pins to.
data-themestringautoEither "light", "dark", or "auto" (follows prefers-color-scheme).
data-open-on-loadbooleanfalseOpen the chat panel automatically on first load. Use sparingly.
data-offset-bottomnumber20Pixels 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:

app.jsjavascript
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.

Watch out
Do not pass server-side secrets in attributes. The identify call runs in the browser; anything you pass is visible to the user. For high-trust identity, add HMAC signing (see below).

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:

javascript
// 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.

MethodDescription
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:

javascript
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:

javascript
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.