A reader who has just failed to find something is looking at your search box, not the corner of the screen. There are two ways to put Ask AI there:
You add markupUse it when
The widget places the buttonNoYou cannot edit your docs theme: Mintlify, GitBook, ReadMe, a hosted help center
Your own buttonYesYou control the page
Both open the same panel.

The widget places the button

Name an element already in your header, usually the search box. The widget puts a labelled Ask AI button next to it:
<script async src="https://widget.kelu.dev/kelu-widget.js"
  data-knowledge-base-id="YOUR_KNOWLEDGE_BASE_ID"
  data-client-key="kl_pk_..."
  data-launcher-button-anchor-selector="#search-bar-entry, #search-bar-entry-mobile"></script>
How it behaves:
  • Every match gets a button. Themes often have separate desktop and mobile headers; list both, as above.
  • It keeps watching. If your header is drawn late or redrawn on navigation, the button comes back.
  • It falls back to the corner. If nothing matches within 10 seconds, the corner button appears instead and the console says why. An invalid selector falls back at once.
  • It replaces the corner button. Add data-launcher-button-floating="true" to keep both. Useful when your theme hides its header controls on phones.
  • Your header’s CSS cannot reach it, so it keeps its own look.
  • It does not shift your header. In a header that centres or spreads its items, the button is laid over the page next to the element instead of being added to the row. To do this it sets position: relative on the element if it had no position.
To find the selector, right-click your search box, choose Inspect, and copy its id or a class.

Settings

AttributeDefaultWhat it does
data-launcher-button-anchor-selectornoneThe element the button goes next to. Every match gets one
data-launcher-button-anchor-positionafterendbeforebegin, afterbegin, beforeend or afterend
data-launcher-button-anchor-wait-ms10000How long to wait for the element before using the corner. -1 waits forever
data-launcher-button-anchor-overlayautomatictrue always lays the button over the page, false always adds it to the row
data-launcher-button-floatingfalseKeep the corner button as well
data-launcher-button-textAsk AIThe label
data-launcher-button-anchor-shaperoundedpill, square or circle. circle shows the icon only
data-launcher-button-anchor-size36pxThe button’s height
data-launcher-button-anchor-text-size13pxThe label’s size
The button uses data-brand-color. If you set data-product-logo, the logo replaces the sparkle icon; add data-launcher-button-image-hidden="true" to keep the sparkle. Component styles such as data-launcher-button-background-color apply to the header and corner buttons alike. data-launcher-button-hidden="true" removes both.
The search view mode has no launcher at all. Open it from your own search box with data-search-input. See Search mode.

Your own button

Draw the button yourself and tell the widget which element it is:
<input id="docs-search" type="search" placeholder="Search the docs" />
<button id="ask-ai">Ask AI</button>

<script async src="https://widget.kelu.dev/kelu-widget.js"
  data-knowledge-base-id="YOUR_KNOWLEDGE_BASE_ID"
  data-client-key="kl_pk_..."
  data-modal-override-open-selector-ask-ai="#ask-ai"
  data-open-query-from="#docs-search"
  data-launcher-button-hidden="true"></script>
Clicking the button opens the chat and asks whatever the reader typed into #docs-search. data-launcher-button-hidden="true" removes the corner button; leave it out to keep both.

Open triggers

Each trigger takes a CSS selector. Use .name for a class and #name for an element id, and separate several with commas.
OpensAttribute
The tab last useddata-modal-override-open-selector
The chatdata-modal-override-open-selector-ask-ai
The Search tabdata-modal-override-open-selector-search
  • Buttons your site draws later, or redraws on navigation, still work.
  • A trigger that is a link opens the widget instead of navigating.

Carrying the query

AttributeDefaultWhat it does
data-open-query-fromthe data-search-input fieldThe field whose text becomes the question. Works with inputs, textareas and contenteditable boxes
data-open-submittrueSend it at once. false puts it in the question box for the reader to send. An empty field sends nothing
A Search tab trigger runs the text as a search instead.

From JavaScript

Call window.KeluWidget.open({ mode: "ai", query, submit: true }) from your own click handler. See Functions.