Widget installation

This page is for the web developer installing the chat widget. It's a single script tag — no build steps, no packages, works with any framework or CMS.

Before you start

  1. Whitelist the site's domains. In the admin area, open the client and go to Settings → Install on your site → Allowed domains. One domain per line; *.example.com covers all subdomains; localhost (with or without a port) is accepted for local testing. On any other domain the widget stays silently absent — no error, no widget.
  2. Find the snippet. The exact snippet — with the correct host and site ID already filled in — is shown in the same section, with a Copy snippet button. The site ID (starts with pk_) is also displayed in the client header, top right.

Option A: floating popup (most common)

Paste before </body> on every page where the chat should appear:

<script async src="https://<your-platform-host>/widget/loader.js" data-site-id="pk_..."></script>

A launcher button appears in the configured corner; clicking it opens the chat panel. The script is async and tiny — it does not block page rendering.

Option B: inline block

Renders the chat as a block inside the page (e.g. on a dedicated support page) instead of a floating popup:

<div id="compent-chat-inline"></div>
<script async src="https://<your-platform-host>/widget/loader.js" data-site-id="pk_..." data-mode="inline"></script>
  • Place the <div> where the chat should appear.
  • To use your own container instead, drop the div and add data-target="#your-selector" to the script tag.
  • Height, max width, alignment and border are configured in the admin under Settings → Widget appearance → Inline embed layout.

Content-Security-Policy

If the site sends a strict CSP, allow the platform host in both directives:

script-src  https://<your-platform-host>;
connect-src https://<your-platform-host>;

Testing locally

  1. Add localhost (or localhost:8080 etc.) to Allowed domains.
  2. Serve your page and load it — the widget appears exactly as in production.
  3. Alternatively, skip local setup entirely and use the Playground tab, which runs the real widget against the real chat API inside the admin.

JavaScript API

The loader defines a global CompentChat function. Calls made before the widget finishes loading are queued and replayed, so you can call it immediately after the script tag.

CallWhat it does
CompentChat("open") / ("close") / ("toggle")Opens/closes the popup panel (ignored in inline mode, which is always visible).
CompentChat("clear")Clears this browser's current conversation and starts the next message in a new conversation. Useful from SPA route handlers or your own "new chat" button.
CompentChat("identify", { userId, name, email, ...vars })Tells the widget who the visitor is. Values are usable as {{tokens}} in the title/welcome texts (see Languages); userId also gives the visitor a per-user rate-limit bucket.
CompentChat("identify", { userToken: <string or function> })Passes a verified identity token signed by your backend — see Identity and access. A function is called automatically whenever a fresh token is needed.
CompentChat("language", "da")Switches the widget language ("en" or "da").
CompentChat("on", event, handler)Subscribes to widget events (below).

Events for CompentChat("on", ...):

  • message:beforeSend — fired before a visitor message is sent; return false from the handler to cancel it.
  • message:beforeRender and message:rendered — fired around each message appearing in the chat.
  • identity:expired — fired once when a static identity token expires, so you can fetch a fresh one and call identify again.

Handler errors never break the widget or the page — every callback is wrapped.

Controlling appearance at runtime

The page can also adjust how the widget looks and behaves — useful for matching a site-wide dark/light toggle live, or giving one page a different placement or size:

CompentChat("theme", { primaryColor: "#0ea5e9", backgroundColor: "#0b1220", textColor: "#e2e8f0", radius: 14, fontFamily: "Inter, sans-serif" });
CompentChat("position", "bottom-left");            // popup corner: "bottom-left" or "bottom-right"
CompentChat("size", { width: 420, height: 560 });  // popup panel size in px (kept within the viewport)
CompentChat("inline", { height: 640, maxWidth: 900 }); // inline block size in px (height 320–1600; maxWidth 0 = fill)
CompentChat("showSources", false);                 // hide the source chips under answers on this page
CompentChat("config", { theme: {...}, position: "...", size: {...}, inline: {...}, showSources: true }); // set several at once

Rules of thumb:

  • Page-scoped only. Nothing is saved — a reload returns to the settings configured in the admin. Use the admin's Widget appearance for the permanent look.
  • Any subset works — pass only the theme keys you want to change. Colors must be 6-digit hex (#0ea5e9); the corner radius is kept within 0–32.
  • Invalid values are silently ignored — a typo can never break the widget or your page. Calls made before the widget loads are queued and replayed, like every other command.
  • size applies to the floating popup; inline applies to the inline block embed.

Example — follow the site's dark-mode switch:

function applyChatTheme(dark) {
  CompentChat("theme", dark
    ? { backgroundColor: "#0b1220", textColor: "#e2e8f0" }
    : { backgroundColor: "#ffffff", textColor: "#111827" });
}

Example — greet logged-in users by name:

<script>
  window.CompentChat = window.CompentChat || function(){(CompentChat._q=CompentChat._q||[]).push(arguments)};
  CompentChat("identify", { userId: "u-123", name: "Anna" });
</script>

Good to know

  • The widget renders inside a shadow DOM — your site's CSS can't accidentally break it, and its styles never leak out.
  • Visitors' conversation, language choice and (if enabled) dragged position/size are remembered per browser via local storage. In Settings -> Widget appearance, Clear chat on page reload keeps the conversation only for the current page life; SPAs can also call CompentChat("clear") whenever their routing should start fresh.
  • Installing the snippet on a not-yet-whitelisted staging domain is safe: the widget simply doesn't render there.

Next: make it match your brand under Widget appearance, or wire up verified logins under Identity and access.