Handoff modes
data-handoff-mode sets what the button does. Setting data-handoff-email or data-handoff-url is enough on its own; the mode follows from it.
data-handoff-mode | What a click does | Needs |
|---|---|---|
email | Opens the reader’s email app with a message to your address, the conversation in the body | data-handoff-email |
url | Opens your URL in a new tab: a ticket form, a chat, a Discord invite | data-handoff-url |
custom | Opens nothing. Fires onAskAIHandoffOpen and then onAskAIHandoffSubmit for your code | A handler |
custom-with-form | The same as custom. There is no built-in ticket form | A handler |
data-handoff-mode="email".
Email handoff
mailto: link, so the message goes from the reader’s own email app and your reply goes straight back to them. Any helpdesk with an email address for new tickets turns it into a ticket.
- Subject: the reader’s first question, up to 120 characters.
- Body: the conversation and the page it was asked on, up to 1,800 characters so the link still opens in every email app.
Handoff to a URL
custom mode when the destination needs the conversation.
Handing off through code
Withdata-handoff-mode="custom", a click fires onAskAIHandoffOpen and then onAskAIHandoffSubmit, with the same payload:
| Field | Type | What it holds |
|---|---|---|
transcript | string | The conversation as text. Each turn starts Question: or Answer:; answers keep their markdown |
conversation | { role, text, citations }[] | The same conversation as data |
threadId | string | The conversation’s id, once there is one |
triggersMatched | string[] | The triggers that showed the button on this answer |
window.Kelu(...) exists only once the widget script has loaded. To register the handler from a script that may run first, preinitialize it. The two events also fire when the button is an email or URL link.
Configuring triggers
data-handoff-triggers is a comma-separated list of when the button appears. It shows under an answer when any listed trigger matches.
| Trigger | Also accepted | The button appears |
|---|---|---|
always | Under every answer. The default | |
uncertain | uncertainty | Under an answer that cited no sources, or that says it is not sure or could not find the answer |
negative-feedback | downvote | Under an answer once the reader presses 👎 on it |
conversation-length | Once the conversation has data-handoff-conversation-length-threshold answers (default 3) |
always.
data-uncertain-answer-callout adds a line of markdown under the same uncertain answers. It is a good place to say what the button is for:
Renaming the button
| Attribute | Default | What it does |
|---|---|---|
data-handoff-button-text | "Create ticket" | The button label, such as “Talk to sales” or “Report a bug” |
handoff-button component, such as data-handoff-button-background-color. See Component styles.
Reference
| Attribute | Default | What it does |
|---|---|---|
data-handoff-mode | From the email or URL | email, url, custom, or custom-with-form (same as custom) |
data-handoff-email | The address the email goes to. Turns the button on | |
data-handoff-url | The page the button opens. Turns the button on | |
data-handoff-triggers | always | When the button appears |
data-handoff-conversation-length-threshold | 3 | Answers before conversation-length matches |
data-handoff-button-text | "Create ticket" | The button label |