Widget SDK
JavaScript Chat Widget
Embed Deskwoot live chat on any website with a single <script> tag. No build step, no dashboard login required from visitors.
1. Install
Paste this snippet into your page template, ideally just before the closing </body>tag. It loads the widget asynchronously, so it won't block rendering.
<script>
window.deskwootSettings = {
widgetToken: "YOUR_WIDGET_TOKEN"
};
(function (d, t) {
var g = d.createElement(t);
var s = d.getElementsByTagName(t)[0];
g.src = "https://deskwoot.com/widget/deskwoot.js";
g.async = true;
g.defer = true;
s.parentNode.insertBefore(g, s);
})(document, "script");
</script>That's it — the chat bubble appears immediately in the bottom-right corner. No npm package, no bundler, no build step. Works inside Next.js, React, Vue, Shopify themes, WordPress, plain HTML, anywhere JavaScript runs.
2. Where do I get the widget token?
- Log into the Deskwoot dashboard (as the account owner, not the end visitor — the widget itself does not require any end-user login).
- Go to Settings → Inboxes.
- Create a new inbox of type Website, or open the existing one.
- Open the Install tab — the ready-to-paste snippet with your inbox-specific
widgetTokenis shown there. Copy it as-is.
One widgetToken = one inbox. Conversations from that widget always land in that inbox, where your agents pick them up. To route to a different team or set of agents, create a second inbox and use its token on a different page.
3. Configuration
All runtime options live on window.deskwootSettings. Only widgetToken is required; everything else has a sensible default.
| Option | Type | Default | Description |
|---|---|---|---|
| widgetToken | string | — | Required. Inbox identifier from the dashboard. |
| color | string | "#2563EB" | Primary brand colour used for send button, outgoing bubble, focus ring. Any valid CSS colour. |
| darkMode | boolean | false | Render the widget with a dark theme. Pair with a dark site; not tied to the visitor's OS setting. |
| position | "left" | "right" | "right" | Which screen corner the launcher bubble appears in. |
| welcomeTitle | string | (from dashboard) | Overrides the welcome headline shown inside the panel header. |
| welcomeMessage | string | (from dashboard) | Overrides the first message shown when a new visitor opens the widget. |
| user | object | undefined | Pre-fills visitor identity (see section 4). |
| embedded | boolean | false | Fills the host container instead of floating in a corner (see section 6). |
Full example
window.deskwootSettings = {
widgetToken: "YOUR_WIDGET_TOKEN",
color: "#2563EB",
darkMode: false,
position: "right",
welcomeTitle: "Hi there!",
welcomeMessage: "How can we help?",
user: {
email: "jane@example.com",
name: "Jane Doe"
}
};4. User identity pre-fill
If the visitor is already logged in on your site, pass their contact details so the conversation arrives with full context instead of as an anonymous visitor.
Authenticated visitor
window.deskwootSettings = {
widgetToken: "...",
user: {
email: "jane@example.com",
name: "Jane Doe"
}
};Deskwoot matches visitors by email. If a contact with that email already exists in the account, the widget attaches to the same contact record — all past conversations, notes and custom attributes are visible to the agent answering.
5. JavaScript API
After the script has loaded, window.deskwootWidget exposes a handful of methods to drive the widget from your own UI — for example a “Contact us” link in the navigation that should open the panel instead of navigating to a support page.
// All methods wait until the widget has finished loading.
window.deskwootWidget.open(); // expand the chat panel
window.deskwootWidget.close(); // collapse the chat panel
window.deskwootWidget.toggle(); // open if closed, close if open
// Current unread agent-message count for this visitor:
console.log(window.__deskwootUnread);6. Embedded mode
Set embedded: true when you are hosting the widget inside a container that should own the full viewport — typically a mobile app WebView, a full-page Contact screen, or a modal that already provides its own chrome.
In embedded mode the launcher bubble, trigger popup and close button are hidden, and the panel stretches to position:fixed; inset:0 with no shadow, no border-radius, no 20px offset. The Deskwoot iOS app uses exactly this mode inside its built-in Contact Support screen.
Bubble is hidden — you need your own trigger.
Since the launcher bubble is suppressed in embedded mode, nothing opens the panel automatically. Wire a button or menu item in your UI to the public JavaScript API:
Minimal trigger
<button onclick="window.deskwootWidget.open()">Contact Support</button>Recommended placements
Three patterns we've seen work well for in-app support:
A — Sidebar / bottom-nav entry (Deskwoot's own approach)
Place a Contact Support item in your existing navigation, next to Settings or Help. Same affordance as a normal route, just opens the panel instead of navigating.
<a href="#" onclick="window.deskwootWidget.open(); return false;" class="nav-item">
<svg class="icon"><!-- chat-bubble icon --></svg>
Contact Support
</a>B — Help menu / dropdown entry
If you already have a Help or Account menu, add a Chat with support row at the top. Pairs nicely with items like Docs, Keyboard shortcuts, Feedback.
<div role="menuitem" onclick="window.deskwootWidget.open()">
Chat with support
<span class="kbd">?</span>
</div>C — Floating action button (bottom-right)
A tiny floating pill that mimics the removed bubble. Useful when your app doesn't have a persistent nav bar.
<button
onclick="window.deskwootWidget.open()"
style="position:fixed;bottom:20px;right:20px;background:#2563eb;color:#fff;border:0;border-radius:9999px;padding:12px 18px;box-shadow:0 6px 20px rgba(0,0,0,.15);cursor:pointer;font-weight:600"
>
💬 Help
</button>Tips
- Call
deskwootWidget.toggle()instead ofopen()if you want the same trigger to close the panel when it's already open. - Show an unread-message badge on your trigger using
window.__deskwootUnread— a number that updates while the panel is closed. - Place the trigger consistently across authenticated pages so users always know where to find support. The global position stops being „hidden chat" and becomes „visible support button".
For the standard (non-embedded) website install you do not need any custom trigger — deskwoot.js renders the bubble itself and handles the click.
7. Content Security Policy
If your site runs with a CSP header, whitelist Deskwoot's origin. Typical minimal configuration:
script-src https://deskwoot.com;
connect-src https://deskwoot.com wss://deskwoot.com;
img-src https://deskwoot.com data:;
style-src 'unsafe-inline';The style-src 'unsafe-inline' is required because the widget injects its own stylesheet. If your CSP forbids inline styles, we can move to a nonce — drop us a line at hello@deskwoot.com.
8. FAQ
Do my visitors need a Deskwoot account to chat?
No. Only you — the site owner — log into the dashboard to answer. Visitors just type into the widget.
Does the widget work in SPAs that change routes client-side?
Yes. Load the script once at app boot (_app.tsx, root.tsx, etc.) and it survives navigation. No re-init needed on route change.
Where is the conversation data stored?
On Deskwoot's servers in the EU. Retention follows your account plan. See the Privacy Policy for details.
Can I test without deploying?
Yes. The snippet runs fine on localhost and on file:// pages. You'll see the conversation appear live in your dashboard inbox.