Datalumo Eisma
Docs · Install & options

Widget SDK

The browser SDK mounts Datalumo search and chat on your site. It loads presentation settings from your widget, streams answers, stores chat history in the browser, and reports analytics. For custom UIs or server-side calls, use the Widget API instead.

Script URL:

https://datalumo.app/widget/v1/datalumo.js

The SDK exposes a global Datalumo object. The API origin is taken from the script URL, so one build works on any host.

Before you embed

  1. Create a search or chat widget in the dashboard.
  2. Add your site domain under the widget's websites list (for example example.com or www.example.com). Browser requests are authorised by the page origin.
  3. Copy the widget key. It looks like {organisation}/{widget} (two public ids). It is safe to put in HTML.

You can also copy a ready-made snippet from the widget page under Add to your site.

Install

Paste before </body>:

Chat bubble

<script src="https://datalumo.app/widget/v1/datalumo.js"></script>
<script>
  Datalumo.chat('ORG_ID/WIDGET_ID').mount();
</script>

Search (modal trigger in a container)

<div id="search"></div>

<script src="https://datalumo.app/widget/v1/datalumo.js"></script>
<script>
  Datalumo.search('ORG_ID/WIDGET_ID', { target: '#search' }).mount();
</script>

Load the script once per page. Call .mount() after the DOM nodes you pass as target or trigger exist.

Entry points

Call Use when
Datalumo.chat(key, options?) Chatbot widget (bubble or inline)
Datalumo.search(key, options?) Search widget (modal or inline)
Datalumo.headless(key, options?) No UI — search, chat, events, and conversation APIs yourself
Datalumo.markdown(text) Turn markdown from chat/summarize into sanitised HTML (headless UIs)

Every call returns a handle. For chat and search, call .mount() to start. Headless is ready immediately.

Shared options

These apply to chat(), search(), and headless():

Option Type Description
user { id, hash? } Tag the visitor. With a server-signed hash, conversation history and ownership work (see Identity).
context object or false Extra page context sent with chat. By default the SDK adds the current page URL and title. Pass an object to merge static fields over that, or false to send no context.
token string Preview Bearer token. Only for the in-app preview; do not use on your public site.

Mount options (chat & search)

On mount, the SDK loads config from the server, then merges your overrides. Dashboard settings are the defaults; anything you pass in the second argument wins except branding (plan-controlled).

Option Type Description
target CSS selector Where to place the UI. Required for inline chat and for search when you want the SDK-rendered box.
trigger CSS selector Use your own element(s) instead of the default launcher or search box. See variants below.
variant string Override the shape from the dashboard. Chat: bubble | inline. Search: modal | inline.
theme string auto | light | dark
accent_light hex string Accent colour in light mode (for example #18181b)
accent_dark hex string Accent colour in dark mode
placeholder string Input placeholder
greeting string Chat only: first assistant message
avatar string Chat only: image URL for the assistant
summary boolean Search only: AI summary above results (uses answer credits)
speech_input boolean Microphone button where the browser supports it
debounce number Search only: ms to wait after typing before searching (default 1000)
default_language string Fallback UI language when the browser language is unsupported

Chat variants

Bubble (default) — floating launcher opens a panel. No target needed.

Datalumo.chat('ORG_ID/WIDGET_ID').mount();

Custom launcher — hide the default button and open from your own control(s):

Datalumo.chat('ORG_ID/WIDGET_ID', {
  trigger: '#open-help',
}).mount();

Inline — panel fills a container (set a height on the container):

<div id="help" style="height: 560px;"></div>
<script>
  Datalumo.chat('ORG_ID/WIDGET_ID', {
    variant: 'inline',
    target: '#help',
  }).mount();
</script>

Search variants

Modal (default) — Cmd/Ctrl+K opens a full search overlay. Optionally render a search-box trigger into target, or bind your own trigger.

// Keyboard only (Cmd/Ctrl+K)
Datalumo.search('ORG_ID/WIDGET_ID').mount();

// Trigger box inside #search
Datalumo.search('ORG_ID/WIDGET_ID', { target: '#search' }).mount();

// Your own button(s) open the modal
Datalumo.search('ORG_ID/WIDGET_ID', { trigger: '.open-search' }).mount();

Inline — input with results listed underneath.

// SDK renders the input into #search
Datalumo.search('ORG_ID/WIDGET_ID', {
  variant: 'inline',
  target: '#search',
}).mount();

// Use an existing <input>; results appear after it (or in target)
Datalumo.search('ORG_ID/WIDGET_ID', {
  variant: 'inline',
  trigger: '#my-search-input',
  target: '#results', // optional
}).mount();

Widget methods

After mount(), chat and search handles support:

Method Applies to Description
mount() both Start loading config and render. Safe to call once; returns the same handle.
destroy() both Remove the widget from the page.
open() both Open the bubble panel or search modal.
close() both Close the panel or modal.
toggle() chat Open if closed, close if open.

Imperative methods queue until the widget is ready, so you can call them right after mount().

Headless client

For a fully custom UI:

const dl = Datalumo.headless('ORG_ID/WIDGET_ID', {
  user: { id: userId, hash }, // optional, signed
  context: { product: 'billing' }, // optional
});

// Search
const hits = await dl.search('refund policy', { limit: 8 });

// Chat (full reply)
const reply = await dl.chat('How do refunds work?');
// reply: { text, conversationId, answerId, sources }

// Chat (stream tokens)
await dl.chat('How do refunds work?', {
  conversationId: reply.conversationId,
  onToken: (delta, full) => { /* update UI */ },
  onStatus: (status) => { /* e.g. searching */ },
});

// Optional AI summary of search results
const summary = await dl.summarize('refund policy', {
  onToken: (delta, full) => {},
});
// summary: { summarized, text }

// Analytics (fire-and-forget)
dl.trackEvent('click', { url: 'https://…', rank: 0, source: 'result' });

// Render markdown safely
container.innerHTML = Datalumo.markdown(reply.text);

Useful properties and helpers on the client:

Member Description
sessionId Analytics session for this tab (auto-created and reused)
identify(user) Set or clear { id, hash } after login
fetchConfig() Presentation config JSON from the server
listConversations() History for a signed visitor
getConversation(id) One transcript
keepConversation(id, kept?) Exempt from expiry (kept: false releases)
deleteConversation(id) Delete one conversation
deleteConversations() Delete all for this visitor

When answer credits run out, chat returns 402. The official chat widget falls back to search results; a headless client should handle that status itself.

Signed visitor identity

To restore chat history for a logged-in user, or to list/keep/delete conversations, prove the user id on your server with the widget's identity signing secret (dashboard → widget → For developers):

$hash = hash_hmac('sha256', (string) $userId, $signingSecret);

Pass the result into the SDK (never ship the signing secret to the browser):

// At init (preferred so every message is tagged)
const chat = Datalumo.chat('ORG_ID/WIDGET_ID', {
  user: { id: String(userId), hash },
}).mount();

// Or after login
const headless = Datalumo.headless('ORG_ID/WIDGET_ID');
headless.identify({ id: String(userId), hash });
await headless.listConversations();

A bad hash is rejected; Datalumo will not treat a failed proof as an anonymous visitor.

See Authentication and Conversations.

Analytics beacon (server-rendered results)

If you search on your server and render your own result list, load the lightweight analytics script so clicks still join the same funnel. Reuse the session_id your server received from search.

<script
  src="https://datalumo.app/widget/v1/datalumo-analytics.js"
  data-widget="ORG_ID/WIDGET_ID"
  data-session="SESSION_FROM_SERVER"
></script>

<a href="https://example.com/docs/refunds"
   data-dl-click
   data-dl-rank="0"
   data-dl-source="result">
  Refunds
</a>
Attribute Required Description
data-widget yes Widget key {organisation}/{widget}
data-session no Session id from the search response; omit to mint a new tab session
data-base no API origin override (defaults to the script origin)
data-dl-click on links Marks a result link for auto click tracking
data-dl-url no Override URL (defaults to href)
data-dl-rank no Result position
data-dl-source no e.g. result, summary

Or initialise manually:

const analytics = DatalumoAnalytics.init({
  key: 'ORG_ID/WIDGET_ID',
  sessionId: '…',
});
analytics.trackClick({ url: 'https://…', rank: 0, source: 'result' });

Your domain must still be on the widget's website list.

Presentation config

On mount the SDK requests:

GET /api/v1/{organisation}/widgets/{widget}/config

Typical payload:

{
  "type": "chatbot",
  "name": "Help",
  "variant": "bubble",
  "accent_light": "#18181b",
  "accent_dark": "#fafafa",
  "theme": "auto",
  "branding": true,
  "summary": false,
  "speech_input": false,
  "placeholder": "",
  "greeting": "",
  "avatar": null,
  "debounce": 1000,
  "default_language": "en"
}

Responses may be cached for up to five minutes. branding follows your plan; clients cannot turn it off by override.

Most appearance and behaviour options are edited in the dashboard (shape, colours, greeting, AI summary, voice input, default language). Use SDK overrides for per-page differences (target, trigger, one-off theme).

Languages

UI chrome (placeholders, buttons, status text) follows the visitor's browser language when supported, otherwise the widget's default_language, otherwise English.

Built-in locales include: en, nl, de, fr, es, it, pt-BR, zh-Hans, zh-Hant, zh-HK, ja, ko, th.

Troubleshooting

Symptom Check
Widget does not load / config fails Domain is on the widget's website list; key is {org}/{widget} public ids
Console: no element matches target / trigger Selector exists when .mount() runs
Chat says wrong widget type Use a chatbot widget with Datalumo.chat, not a search widget
Conversation history empty Pass signed user.id + user.hash; signing secret must match
No analytics in the dashboard Domain allowlist; wait for first search or chat; for custom results use the analytics beacon
Branding still shows Controlled by plan, not by client override

Related