Web SDK Overview
The Web SDK puts the Qafka assistant on a website or web app. It ships two ways:
- CDN snippet — a single
<script>tag. No build step, no install — works on any site, including WordPress via the dedicated plugin. - npm package (
@qafka/web) — a framework-agnosticcreateQafka()bootstrap plus a React component, for apps that already have a build pipeline and want programmatic control (callbacks, a visitor grouping id, dynamic context).
@qafka/web isn’t on the public npm registry yet — contact Qafka for access. The CDN snippet works without it.
Both distributions are built from the same engine and render the same chat UI, voice mode, and in-chat media cards.

Which one do I use?
| CDN snippet | npm package | |
|---|---|---|
| Setup | Paste a script tag | npm install @qafka/web |
| Best for | Public marketing/content sites | Web apps with signed-in users, custom logic |
| Group messages by visitor | Not supported | endUserId, endUserData |
| Programmatic control | None | sendMessage, open, close, openVoice, update, callbacks |
| Where | Dashboard’s website onboarding, or Quick Start (Website) | npm & React |
CDN snippet
<script src="https://cdn.qafka.com/v1/qafka.js" data-key="qafka_pk_..." async></script>| Attribute | Required | Description |
|---|---|---|
data-key | Yes | Your project’s Web (publishable) key. Without it the loader no-ops. |
data-api-url | No | Overrides the backend URL. Defaults to https://api.qafka.com. |
data-lang | No | Forces the widget’s UI language (tr or en). Omit to auto-detect from the visitor’s browser. |
data-agent-cursor | No | Opt-in agent cursor for navigation — see Agent Cursor below. A bare attribute or ="true" turns it on. |
Get the exact tag, with your key filled in, from your project’s dashboard: Onboarding (for a new site) or API Keys (anytime after).
Allowed domains
A chat session only starts from an origin that’s on both the project’s registered Websites and, if the key restricts itself to specific sites, one of those — any other page embedding the key gets rejected. A key’s own restriction can only narrow what Websites allows; it never allows a site on its own.
Adding a site through the website onboarding flow registers its domain automatically as the project’s own site, and the Web key it creates is restricted to that domain. For any other domain the widget needs to run on (a staging environment, localhost during development, a second site), register the domain on the Websites page, then create a separate Web key for it on the API Keys page (the number of keys per project depends on your plan) — leave that key’s website restriction empty to let it work on any of the project’s registered websites.
Enter the full origin, including scheme and port, for anything that isn’t a plain https://host — for example http://localhost:3000, not just localhost. A bare host is assumed to be https://, and scheme/port must match exactly.
How many distinct site domains your account can register depends on your plan.
To embed the widget on someone else’s site instead — a partner or publisher site outside your own domain — add it as a partner entry on the dashboard’s Websites page and use a Web key whose website restriction is empty or includes that site.
See API Key Security for the full origin-allowlisting model.
npm package
npm install @qafka/webimport { createQafka } from '@qafka/web'
const qafka = createQafka({
publishableKey: 'qafka_pk_...',
mode: 'floating',
})A React component is also available at @qafka/web/react. See npm & React for the full setup, and Options Reference for every option.
Visitor identity & tools on web
Every web session — CDN snippet or npm package alike — is minted at the anonymous trust tier server-side. Passing isAuthenticated doesn’t change that: there is no identified web trust tier yet, so it’s used only for navigation screen filtering, not for tool access. Passing endUserId (and optionally endUserData) attaches a client-supplied grouping id to the conversation — useful for tying messages to a known user in your own app — but it isn’t a verified identity and doesn’t change what the assistant can do.
This matters for tools: a tool is available on a web session only if its Platform includes Web and its Web access is set to “Open on web (incl. anonymous)” in the dashboard’s tool editor — the default, “Closed on web — native/api-key only”, hides the tool from every web session regardless of platform. Choose the Web access setting carefully for any side-effecting tool (email, webhook, writes) — opening it up exposes that action to anonymous visitors, including bots.
Media cards
When the assistant suggests a video, social post, or document link (embed/document destinations), the web widget renders it as an in-chat media card — a title, description, optional image, a play button for embeds, and a link to the original. See External Navigation › Media Destinations for the full destination-type reference.
Voice
Both distributions support voice mode. On the web, an in-call tool can also request a file upload from the visitor — a capability the React Native SDK’s voice mode doesn’t have. See Voice for setup, quotas, and platform differences.
Agent cursor
An opt-in feature (agentCursor / data-agent-cursor, off by default): when the assistant navigates the visitor to another page, a visible cursor glides to one of the page’s own links for that destination and clicks it, instead of jumping directly. If no such link can be clicked safely, it falls back to navigating normally. Pressing Esc cancels a run in progress. When the visitor’s OS requests reduced motion, the glide itself is skipped — the link is still clicked, just without the animated cursor.
WordPress
Running WordPress? Use the WordPress plugin instead of hand-editing the snippet — it adds the script tag for you from a settings page.