DokumentasjonGuide for AI-agenterMarkdown
Implementing Snakkbar in a site — guide for AI agents
You are an agent with control over a website's code and want to add Snakkbar to it. Follow these steps in order. Every step ends with a check; do not move on until it passes.
0. Gather inputs
Ask the human for anything you cannot find yourself:
| Input | Example | Where it comes from |
|---|---|---|
SNAKKBAR_HOST | https://www.snakkbar.app | Snakkbar |
TENANT_ID | amatec | Snakkbar (admin → Innstillinger) |
SNAKKBAR_SECRET_KEY | sk_snakkbar_… | Only needed for steps 3 and 4. Admin → Innstillinger → API-nøkler. Store as a server secret. |
| Production origin(s) | https://www.example.no, https://example.no | The site you control |
Check: curl $SNAKKBAR_HOST/api/v1/tenants/$TENANT_ID/config returns JSON with the assistant's name.
Then decide, per side, how deep to integrate:
- Visitor side: stock widget (default — choose this unless the human wants a custom chat design) or own UI with the SDK.
- Staff side: hosted panel at
$SNAKKBAR_HOST/panel(nothing to build), stock admin embedded in the site's own back office (step 3), or own UI with the SDK (step 5).
1. Allow the site's origins
The widget and embedded admin only work on allowed origins. As an admin in the Snakkbar admin (Innstillinger → Nettsteder som kan vise chatten) add every origin the site is served from. If you have an admin operator token, you can do it via the API:
curl -X PATCH "$SNAKKBAR_HOST/api/v1/operator/tenant" \
-H "authorization: Bearer $OPERATOR_TOKEN" -H "content-type: application/json" \
-d '{"allowedOrigins":["https://www.example.no","https://example.no"],"siteHosts":["www.example.no","example.no"]}'siteHosts are the hosts the assistant may read for answers (and where staff may send visitors).
Check: GET /operator/tenant lists the origins. (Local development on http://localhost:* works
without this.)
2. Add the visitor widget
Add once, on every page, just before </body>:
<script src="https://<SNAKKBAR_HOST>/widget.js" data-tenant="<TENANT_ID>" defer></script>Framework recipes:
- Next.js (App Router) — in
app/layout.tsx:tsximport Script from "next/script"; // inside <body>: <Script src={`${process.env.NEXT_PUBLIC_SNAKKBAR_HOST}/widget.js`} data-tenant="<TENANT_ID>" strategy="afterInteractive" /> - React SPA (Vite etc.) — put the tag in
index.html. - Astro / SvelteKit / Nuxt — put the tag in the root layout's HTML.
- WordPress — theme footer (
footer.php) or a "header & footer scripts" plugin. - Content Security Policy — see widget.md.
Options and the JavaScript API (Snakkbar.open(), events, identified visitors) are in
widget.md. Add a "Chat med oss" link anywhere with onclick="Snakkbar.open()".
Live visitors and consent. The widget also reports every visitor as a live visitor (pages,
and the cursor while staff watch); this is on by default. Ask the human whether the site needs
consent for this kind of tracking. If it has a consent banner, load the widget only after
consent; if consent is needed but there is no banner, or they don't want it, turn it off with
PATCH /api/v1/operator/tenant { "liveVisitors": false } (or Innstillinger in the admin).
Details in widget.md.
Live view. For staff's «Se live» to show the real page, the site must allow being framed by
the admin's origin: add frame-ancestors 'self' $SNAKKBAR_HOST (plus the origin of the site's own
admin, if you do step 4) to the site's CSP, and remove any X-Frame-Options header. See
admin-embed.md.
Check, in a real browser on the site:
- A round launcher appears bottom-right; no console errors.
- Clicking it opens the chat with the assistant's name and welcome text.
- Sending "Hei" streams an answer.
- The network tab shows no
origin_not_allowed(403) responses. - With live visitors on:
POST /api/v1/visitor/activitygoes out about every 10 s, and the visitor shows up in the admin under «Besøkende».
3. (Optional) Identified visitors
If the site has logged-in users, add a backend endpoint that returns a visitor token for the
current user, and call Snakkbar.identify(fn) after login and Snakkbar.identify(null) on
logout. Code in widget.md. Send the user's name, email,
phone, company (and any attributes staff should see) with the token request; that is the
trusted source. Where the page knows the user but you can't mint tokens, use
Snakkbar.setUser({ ... }) or data-user-* instead (unverified, see
widget.md).
Check: log in on two browsers as the same user; the chat history (☰ menu) is the same in both, and staff see the user's name on the visitor.
4. (Optional) Staff inbox inside the site's own admin
- Backend: an authenticated endpoint that exchanges the logged-in staff user for an operator
token (
POST $SNAKKBAR_HOST/api/v1/server/operator-tokens). Map your user id toexternalIdand your admin flag torole. Code in admin-embed.md. - Admin page: a container with a fixed height,
<script src="$SNAKKBAR_HOST/admin.js">andSnakkbar.mountAdmin(container, { host, token })wheretokenfetches from your endpoint and caches until shortly beforeexpiresAt. Code in admin-embed.md. - The admin page's origin must be an allowed origin too (step 1).
Check:
- The inbox loads and shows the staff member's name (Innstillinger → Profil).
- Turn on Tilgjengelig; the widget launcher on the public site shows that person's face.
- From the public site, write "kan jeg snakke med et menneske?" — the inbox alerts «Spør etter deg»; join and reply; the visitor sees the reply live.
- Non-staff users get 401/403 from your token endpoint.
5. (Optional) Fully custom UI
Use the SDK instead of the stock UIs: sdk.md (visitor and staff clients, React hooks,
rendering rules) and realtime.md. Follow the rendering rules in sdk.md so
translations, product cards, suggestions, navigation and receipts behave like the stock UI. On a
custom visitor UI, call client.startTracking() once per page load (on every page, so live
visitors and the live view work) and client.updateProfile(...) when the user is known; respect
the consent decision from step 2.
Check: the same scenario as step 4's checks works end to end with your UI.
6. Hand-over notes for the human
Tell the human:
- where the widget tag lives in the code base and how to remove it;
- the env vars you added (
SNAKKBAR_HOST,SNAKKBAR_SECRET_KEY) and that the key must be rotated if it leaks; - which origins you allowed;
- whether live visitors are on, and how consent is handled (or that
liveVisitorsis off), and whether you changed the site's CSP/X-Frame-Optionsfor the live view; - that assistant behaviour (name, portrait, tone, instructions, welcome text, knowledge) is managed in the Snakkbar admin, not in the site's code.
Troubleshooting
| Symptom | Cause / fix |
|---|---|
| Launcher never appears | Script blocked (CSP, ad blocker) or wrong data-tenant. Check console and the config request. |
403 origin_not_allowed | Add the exact origin (scheme + host + port) to allowed origins. |
| Answers never arrive, but no error | A proxy buffers text/event-stream. Exclude /api/v1/* from buffering, or call Snakkbar directly (it is a different origin anyway). |
401 unauthorized in the embedded admin | Token endpoint returns an expired token; respect expiresAt. |
| Staff face never shows on the launcher | Staff must be Tilgjengelig and have the admin open (heartbeats keep them online). |
| Widget looks off-brand | Set the brand colour in the admin, or data-accent="#rrggbb". |
| No visitors under «Besøkende» | liveVisitors is off, the widget is loaded only after consent that wasn't given, or (custom UI) startTracking() is never called. |
| «Se live» shows only a schematic page | The site refuses framing: allow the admin's origin in frame-ancestors and drop X-Frame-Options. |