These options control what the widget does. Each is a data-* attribute on the script tag. Labels, titles, placeholders and styling are on Component styles.
Each option has one name. Older names, including kapa.ai’s, still work on existing tags and are listed in Legacy and kapa.ai names.
Core parameters
| Attribute | Required | Description |
|---|
data-knowledge-base-id | One of the two ids | The knowledge base to answer from |
data-widget-id | One of the two ids | A widget integration from the dashboard. It names its own knowledge base, and its settings fill in every option the tag leaves out |
data-client-key | Yes | Public client key (kl_pk_...). If the key has Allowed origins, any other site gets 403 |
data-product-name | Recommended | Name in the header, placeholder and welcome line. Default: the knowledge base’s name, else “Ask AI” |
data-product-logo | Recommended | Header logo, launcher image and welcome icon. Skipped if the image fails to load |
data-brand-color | Recommended | Accent colour. Default #343CED. See Theming |
data-base-url | No | API address. Default https://app.kelu.dev. Change it only for a self-hosted deployment |
<script
async
src="https://widget.kelu.dev/kelu-widget.js"
data-knowledge-base-id="YOUR_KNOWLEDGE_BASE_ID"
data-client-key="kl_pk_..."
data-product-name="Acme"
data-brand-color="#6306B6"
data-product-logo="https://example.com/logo.png"
></script>
Language
| Attribute | Description | Default |
|---|
data-language | Language of the widget’s own text: buttons, labels, placeholders. The answer is in English unless the reader asks in another language or the widget’s customization sets one | "en" |
Supported: en English, cs Czech, de German, es Spanish, fi Finnish, fr French, it Italian, ja Japanese, ko Korean, nl Dutch, pt Portuguese, ru Russian, zh Chinese. A region is ignored (pt-BR uses pt). Anything not translated shows in English.
Opening the panel
The panel opens from the launcher and from Cmd+K or Ctrl+K. The shortcut closes it again, and Esc always closes it.
| Attribute | Description | Default |
|---|
data-modal-open-by-default | Open the panel as soon as the page loads | "false" |
data-modal-open-on-command-k | "false" turns the keyboard shortcut off | "true" |
data-hotkey | The key pressed with Cmd/Ctrl. "none" turns the shortcut off | "k" |
data-modal-command-k-search-mode-default | The shortcut opens the Search tab instead of the chat. Needs search on | "false" |
data-modal-override-open-selector | CSS selector. Clicking a match opens the panel on its current tab | Not set |
data-modal-override-open-selector-search / -ask-ai | The same, opening the Search tab or the chat | Not set |
data-open-query-from | Field whose text becomes the question when one of these elements is clicked, usually your search box. Works with inputs and editable elements | data-search-input |
data-open-submit | Send that text at once. "false" fills it in and waits | "true" |
data-render-on-load | "false" loads the settings but draws nothing until render() is called | "true" |
The click listeners work for buttons your site draws later too.
kapa.ai turns Cmd+K off by default; Kelu turns it on. Set data-modal-open-on-command-k="false" if your site already uses Cmd+K for its own search.
Conversation
| Attribute | Description | Default |
|---|
data-persist | "session" keeps the conversation across pages and reloads until the tab closes. "none" forgets it on every page load | "session" |
data-instant-search | Show matching pages above the question box as the reader types | "true" |
data-uncertain-answer-callout | Markdown added under an answer that cited nothing or said it was not sure. The uncertain hand-off trigger uses the same test | Not set |
Starter questions, the welcome line and placeholders are under Example questions.
Search
Search mode adds a Search tab that lists matching pages without writing an answer. See Search mode.
| Attribute | Description | Default |
|---|
data-search-mode-enabled | Add the Search tab | "false" |
data-search-mode-default | Open on the Search tab | "false" |
data-search-keyboard-nav-enabled | "false" turns off arrow keys in the results | "true" |
To limit what search covers, use source groups. Results are ordered by relevance.
Source groups
| Attribute | Description | Default |
|---|
data-source-group-ids | Comma-separated source group ids. Chat, search and form deflection use only these groups | Not set |
This can narrow what the client key reaches, never widen it. setSourceGroupIDs() changes it while the page is open.
Conversation hand-off
A Create ticket button under answers that passes the conversation to a person. It appears only once one of the first three options is set. See Conversation handoff.
| Attribute | Description | Default |
|---|
data-handoff-email | Address the button emails | Not set |
data-handoff-url | A page the button opens instead: a ticket form, a chat, a Discord invite | Not set |
data-handoff-mode | email, url or custom. custom opens nothing and fires onAskAIHandoffOpen for your code | Set by the email or URL |
data-handoff-triggers | When the button appears, comma-separated: always, uncertain, negative-feedback, conversation-length | "always" |
data-handoff-conversation-length-threshold | Answers before conversation-length matches | 3 |
Consent
| Attribute | Description | Default |
|---|
data-consent-required | Open on a consent screen. Nothing is sent until the reader accepts. The answer is remembered in the browser per knowledge base | "false" |
The screen’s wording is under Consent screen.
Analytics
See User tracking and User satisfaction.
| Attribute | Description | Default |
|---|
data-user-analytics-cookie-enabled | "false" sends no anonymous reader id. The id is random and kept in localStorage | "true" |
data-user-analytics-fingerprint-enabled | Build the id from browser details instead of storing one. Wins over the stored id | "false" |
data-user-id / data-user-email | A signed-in reader, attached to their questions. window.keluSettings.user ({ uniqueClientId, email }) does the same from code | Not set |
data-exit-feedback-enabled | "false" stops the “Did you find what you were looking for?” question | "true" |
data-user-satisfaction-feedback-enabled | Offer a 1–5 rating once, after a few answers | "false" |
data-user-satisfaction-after-answers | Answers before that rating is offered | 3 |
Bot protection
| Attribute | Description | Default |
|---|
data-bot-protection-mechanism | "recaptcha" sends a reCAPTCHA v3 token when your deployment requires one. "none" sends none, so a deployment that requires tokens refuses the requests | "recaptcha" |
The widget asks the server whether a token is needed, so there is nothing else to set. "hcaptcha" is not supported: it logs a warning and reCAPTCHA is used.
A Use MCP button in the header gives readers ready-made commands for adding this knowledge base to Claude Code, Codex, Cursor or VS Code as an MCP server.
| Attribute | Description | Default |
|---|
data-mcp-enabled | "true" always shows the menu. "false" always hides it | Decided by the server |
data-mcp-server-url | The address the copied commands use. Set it when the API sits behind your own proxy or domain | The knowledge base’s own MCP server, else <data-base-url>/mcp |
Left unset, the menu appears when the client key has Allow MCP access on, or when the knowledge base has a public MCP server. With a public server the commands carry no key and readers sign in. The button label and description are under MCP button.
Customization
The voice the widget answers in (assistant name, response style, guardrails) is a customization. It has no attribute: assign it to a widget integration in the dashboard and embed that with data-widget-id. Without one, the widget answers in the knowledge base’s own answer style.