Embed the DPI assistant into your web app as a floating button + chat popup.
<script> tag. No login, no SDK, no build step,
and no secret in the browser. The live assistant on this page (bottom-right) was added with exactly the tag below.
Paste this just before </body> on any page where the assistant should appear:
<script src="https://dpi-widget.leantransitionlabs.com/dpi-widget.js" data-org="Datapoint" data-client-id="pk_your_client_id" data-public-session ></script>
Replace pk_your_client_id with the public client id DPI issues you.
A launcher button appears in the corner; clicking it opens the chat, scoped to your tenant.
All configuration is via data-* attributes on the script tag.
| Attribute | Required | Values | Default | Notes |
|---|---|---|---|---|
data-client-id | Yes | your pk_… id | — | Public client id (safe to expose in the page). |
data-public-session | Yes* | present / absent | absent | Enables the no-server shared session (see §4). *Required for the one-tag flow. |
data-org | No | any string | Datapoint | Name shown in the widget header. |
data-position | No | right | left | left | Which corner the launcher sits in. |
data-mode | No | floating | sidebar | fullscreen | floating | Panel layout. |
data-theme | No | light | dark | light | Colour theme. |
data-auto-open | No | present / absent | absent | Open the panel automatically on load. |
After the script loads, a small API is available on window.DPIChat:
DPIChat.open(); // open the panel DPIChat.close(); // close it DPIChat.toggle(); // toggle DPIChat.setTheme('dark'); // 'light' | 'dark' DPIChat.setMode('sidebar'); // 'floating' | 'sidebar' | 'fullscreen' DPIChat.sendMessage('What is my OEE this week?'); // open + send
None of this is required for a basic embed — the launcher button handles everything.
With data-public-session, the widget authenticates itself using only the public
client_id: no login prompt, no server work on your side. The chat runs as a
shared, anonymous session locked to your tenant — all users of the page share one assistant identity
(no per-user history/isolation). This is the recommended starting point.
If you need each of your logged-in users to have their own isolated conversation/scope, drop
data-public-session and instead register a token provider that fetches a short-lived
JWT from a small /dpi-token endpoint on your server (the endpoint signs with your
client secret, which stays server-side and never reaches the browser):
<script src="…/dpi-widget.js" data-client-id="pk_your_client_id"></script> <script> DPIChat.setTokenProvider(async () => { const r = await fetch('/dpi-token', { credentials: 'include' }); return (await r.json()).token; // a short-lived JWT minted by YOUR server }); </script>
Ask the DPI team for the per-user token contract (claims + signing) and a snippet in your stack.
https://dpi-widget.leantransitionlabs.com.dpi-widget.js is cached up to 4 hours; end users pick up updates automatically. While testing, hard-reload (Cmd/Ctrl+Shift+R) to bypass it.If your app sets a Content-Security-Policy, allow the DPI origin:
script-src https://dpi-widget.leantransitionlabs.com; frame-src https://dpi-widget.leantransitionlabs.com; connect-src https://dpi-widget.leantransitionlabs.com;
| Symptom | Cause / fix |
|---|---|
| “Couldn’t sign you in” | You’re running an old cached dpi-widget.js. Hard-reload, or in DevTools → Network tick Disable cache and reload. |
| Launcher doesn’t appear | The script didn’t load — check the src is reachable and not blocked by CSP. |
| “Service is starting / unavailable” | The DPI backend is warming up; it retries automatically. If it persists, contact the DPI team. |
DPI issues you a public client_id (and, for per-user mode, a server-side secret) and
enables your tenant. Contact the DPI / LTS team to get set up, then drop in the tag from §1.