The widget attaches a reader id to every question, so analytics can count distinct readers and show what one reader asked over time. By default the id is random and anonymous. You can turn it off, build it from the browser instead, or replace it with your own user’s id.

Anonymous user tracking

The first time the widget needs a reader id, it creates a random one, such as anon_k3j9x2mq…, and keeps it in the browser’s localStorage under kl:anon. It is not a cookie, so it is not sent to your servers with page requests.
  • It identifies a browser, not a person, and holds nothing about the reader.
  • It lasts across reloads and visits until the reader clears their site data.
  • The Support Form Deflector on the same site uses the same id, so a reader who asks the assistant and then files a ticket counts once.
  • If the browser blocks storage, no id is sent.

Disabling user tracking

<script async src="https://widget.kelu.dev/kelu-widget.js"
  data-knowledge-base-id="YOUR_KNOWLEDGE_BASE_ID"
  data-client-key="kl_pk_..."
  data-user-analytics-cookie-enabled="false"></script>
On a widget integration, switch off Anonymous visitor id in the dashboard’s Behaviour tab instead. With tracking off, questions carry no stored id and the widget does not report being opened. Questions still count in totals, but not in distinct-reader figures. The attribute keeps kapa’s name, “cookie”, although the id lives in localStorage.

Fingerprint tracking

data-user-analytics-fingerprint-enabled="true"
Instead of storing an id, the widget builds one, such as fp_1x9k2p, from the browser’s user agent, language, timezone and screen size. It survives cleared site data, and two readers with identical setups can share it. When on, it is used instead of the stored id. It is still a fingerprint, so check your privacy policy before turning it on.

Identifying signed-in readers

When your site knows who the reader is, pass their id and email, and every question is attributed to them. A signed-in reader always wins over the anonymous id and the fingerprint.
<script async src="https://widget.kelu.dev/kelu-widget.js"
  data-knowledge-base-id="YOUR_KNOWLEDGE_BASE_ID"
  data-client-key="kl_pk_..."
  data-user-id="user-123"
  data-user-email="jane@example.com"></script>
window.keluSettings is read once, when the script tag sets up the widget, so set it before the tag. If you call KeluWidget.init() yourself, pass user: { id, email } there. When both are present, data-user-id and data-user-email win. kapa’s metadata object (company, name) is not sent.
An email is personal data. Collect it only where your privacy policy and the reader’s consent allow. See PII and data retention for how Kelu stores and masks it.
data-consent-required="true"
The panel opens on a consent screen and the question box stays locked until the reader accepts. Until then, no question is sent, the widget does not report being opened, and no anonymous id or fingerprint is created. An id your page supplies (data-user-id, setUser()) is used as given. Accepting is remembered in localStorage per knowledge base. Declining closes the panel, and the screen shows again next time. The wording is under Consent screen. To use your own consent banner instead, load the widget with data-render-on-load="false" and call KeluWidget.render() once the banner is accepted.

What the widget stores in the browser

KeyStorageHoldsCleared
kl:anonlocalStorageThe anonymous reader idBy the reader
kl:consent:<knowledge base id>localStorageyes once consent is givenBy the reader
kl:expanded:<knowledge base id>localStorageWhether the reader left the panel expandedBy the reader
kl:chat:<widget or knowledge base id>sessionStorageThe conversation, so it survives page changesWhen the tab closes. Not written with data-persist="none"

Reference

AttributeDefaultWhat it does
data-user-analytics-cookie-enabledtruefalse sends no stored id and no “opened” report
data-user-analytics-fingerprint-enabledfalseBuild the id from the browser instead of storing one
data-user-idYour own id for a signed-in reader
data-user-emailThe signed-in reader’s email
data-consent-requiredfalseAsk for consent before anything is sent
data-persistsessionnone keeps the conversation in memory only
A Support Form Deflector on the same tag uses the same tracking attributes and the same data-user-id and data-user-email, so one reader is one reader on both.