Skip to main content
The widget is a chat bubble your visitors talk to; the conversations land in the Linkiasoft inbox alongside WhatsApp, Messenger and the rest. Setting it up in the app is covered in Website chat — this page is the part that goes in your codebase.

The snippet

Put it before the closing </body> tag of every page that should have the bubble. Your data-website-id is on the channel’s Install tab. That is the whole installation. Everything below is optional.
The website id is public and meant to be. It sits in a page anyone can read the source of. What makes it safe is the domain allowlist on the channel: the widget refuses to boot on any origin the channel’s owner hasn’t listed, so a copied id is useless elsewhere.Never put an API key in a page. A Linkiasoft API key carries workspace-wide access — see Authentication.

What it costs your page

  • The script is async and boots when the browser is idle, so it is never on the critical path to your first paint.
  • The chat UI itself is an iframe on our origin, and it is not fetched until somebody opens the panel — or until a reply arrives for a visitor who has one waiting.
  • The live connection is a single EventSource. No polling, no WebSocket upgrade to be mangled by a corporate proxy, no client library.
The iframe is also what keeps your CSS out of the widget and the widget’s CSS out of your page. Nothing we ship can restyle your site, and nothing your site does can break the composer.

Calling it before it loads

If you need to talk to the widget from your own code — identify a signed-in user, open it from your own button, listen for events — add the queue stub above the script tag:
Calls made before the loader arrives are queued and replayed once it does, so nothing is lost and nothing has to wait for an onload. The full command list is in the JavaScript API.
If your site sets a script-src policy with a nonce, the inline stub above needs that nonce. The plain one-line snippet does not — it has no inline script, which is exactly why it is the default.

Overriding settings on one page

The dashboard holds the defaults. A single page can override the look, the launcher and the greeting before boot:
Set it before the loader runs, or pass the same object through Linkia('init', …). Copy other than the greeting stays server-side deliberately: support can fix a typo in the offline message without a customer redeploying their site.

Your own launcher

Any element carrying data-linkia-open opens the widget, and any element carrying data-linkia-unread receives the unread count as its text:
Both are bound for elements added later too, so this works in a framework that renders the button after boot. Set hideLauncher: true if you don’t also want our bubble.

Single-page apps

The widget survives client-side navigation on its own — it is not tied to a route, and the loader ignores a second injection. So:
  • Inject the script once, in your root layout or index.html, not in a page component.
  • Don’t remount it per route. If you must remove it entirely, call Linkia('destroy').
  • Re-identify only when the user changes, not on every navigation.

Content Security Policy

If your site sends a CSP, allow our origin in four directives:
connect-src covers both the widget’s requests and its EventSource stream. img-src needs whatever host serves your logo and any images your visitors send, which is our media CDN unless you set your own.
A blocked directive shows up in the browser console as a CSP violation naming the directive that refused. That message is the fastest route to the fix — read it before changing anything else.

What the widget stores

The token lives in your page’s storage rather than the iframe’s on purpose: Safari and Firefox partition storage inside a cross-origin iframe, so a token kept there would be discarded on every reload and every returning visitor would look new. No cookies are set, and nothing is shared with any other site.
Call Linkia('logout') wherever your own sign-out runs. On a shared computer, the next person to open the widget would otherwise be reading the previous person’s conversation.

Limits

Exceeding one gets a 429; the widget shows the message as unsent with a retry rather than losing it.

When it doesn’t appear

Work down in order — the first four cover almost everything:
  1. Console. The widget logs one line beginning [Linkia chat] when it refuses to start, and it names the reason.
  2. The domain allowlist. 403 from /boot means this origin isn’t listed. acme.com covers www.acme.com; a subdomain needs *.acme.com.
  3. The website id. 401 means unknown or paused — check the channel is connected and the id matches the Install tab.
  4. CSP. A violation in the console names the directive to add.
  5. Ad blockers. Several block chat widgets by hostname. Test in a clean profile.

Next

JavaScript API

Open and close it, identify visitors, listen for events.

Identity verification

Sign the user id on your server so a browser cannot claim someone else’s.