JavaScript API
Every method and event of the Ticketping chat widget, for the script tag, npm and the framework adapters.
The same methods work everywhere. The examples use the queued form, which is safe to call before the widget has loaded.
Three ways to call it
Queued, with the script tag. Calls wait until the widget loads, then run in order:
window.Ticketping ||= (...args) => (Ticketping.q ||= []).push(args)
Ticketping('open')Direct, once the widget has loaded. Use this when you need a return value:
Ticketping('on', 'ready', () => {
console.log(Ticketping.getUnreadCount())
})npm, with the same methods on the imported object. Nothing touches the page until init, so it’s safe to import during server rendering:
import { Ticketping } from '@ticketping/chat-widget'
Ticketping.init({ publishableKey: 'pk_...' })
Ticketping.open()When the queue replays, on and off run first, then init, preview and consent in the order you called them, then everything else. A handler you queue after init still sees ready and any error from init. A consent('pending') queued before init still stops the boot.
init
Starts the widget. With the script tag, data-key calls it for you, so you only call it yourself to pass options. Then leave data-key off the tag.
Ticketping('init', {
publishableKey: 'pk_...',
locale: 'en-GB',
hideLauncher: false,
consent: 'granted',
appearance: {
accentColor: '#0f766e',
colorMode: 'auto',
position: 'bottom-right',
launcher: { icon: 'chat', label: 'Help' }
},
texts: {
greetingTitle: 'Hi there',
greetingBody: 'Ask us anything. We usually reply in a few minutes.',
composerPlaceholder: 'Write a message…'
},
features: { gifs: false }
})| Option | Type | Notes |
|---|---|---|
publishableKey | string | Required. pk_ and 24 letters or digits, from Settings → Widgets |
locale | string | A BCP 47 tag like fr or en-GB. Defaults to the browser’s language |
hideLauncher | boolean | Hide the floating button, for example to open the widget from your own button |
consent | 'granted', 'pending' or 'denied' | Defaults to 'granted'. See consent |
appearance | object | accentColor, colorMode (light, dark, auto), position (bottom-right, bottom-left), launcher (icon: chat, help or none; label) |
texts | object | greetingTitle, greetingBody, composerPlaceholder, conversationStarter |
features | object | ai, attachments, emailCapture, emoji, gifs. You can only set these to false |
apiUrl | string | Overrides the API origin. Only for a self-hosted backend in local development |
Options you set in code beat the dashboard. Features are the exception: code can turn one off, but not on if the dashboard has it off. See Configuration.
init runs once. A second call is ignored with a console warning; use update to change options later. An invalid key emits an error with code invalid_publishable_key.
consent
Use this with a cookie banner. With consent: 'pending', the widget stores nothing and doesn’t contact Ticketping’s API until you call:
Ticketping('consent', 'granted')Ticketping('consent', 'denied') stops the widget and deletes everything it stored in the browser.
identify
Tells the widget who the signed-in user is.
Ticketping('identify', {
userId: 'u_123',
email: 'ada@acme.com',
name: 'Ada Lovelace',
company: { id: 'acme', name: 'Acme' },
attributes: { plan: 'pro' },
getToken: async () => {
const res = await fetch('/api/ticketping-token', { method: 'POST' })
if (!res.ok) throw new Error(`Ticketping token request failed (${res.status})`)
return res.text()
}
})- With
getToken, the identity is verified. The widget callsgetTokenfor a fresh token whenever it needs one, and Ticketping takes the user’s details from the token. See Identity verification. - Without
getToken, the details are sent unsigned and the identity is unverified. - Calling
identifyagain with the sameuserIdwhile the session is still valid doesn’t callgetTokenagain, so it’s safe to call on every page load. - A different
userIdlogs the previous user out first.
If getToken throws or returns something other than a token, the widget stays anonymous and emits error with code get_token_failed. If Ticketping refuses the token, the code is token_invalid and details.reason says why (see When a token is refused).
logout
Ticketping('logout')Call it when the user signs out. The widget forgets the user and their conversations on this device and starts as a new anonymous visitor. It does nothing for a visitor who was never identified.
update
Call it after client-side navigation so your team sees the page the visitor is on, or to change options after init:
Ticketping('update')
Ticketping('update', { page: { url: location.href, title: document.title } })
Ticketping('update', { attributes: { plan: 'enterprise' }, appearance: { accentColor: '#7c3aed' } })update takes page, attributes, hideLauncher, locale, and the same appearance, texts and features as init. With no options, it sends the current URL and title.
setContext
Adds details about what the visitor is doing, shown to your team next to the conversation. It merges into earlier calls.
Ticketping('setContext', { orderId: 'ord_123', screen: 'checkout' })Keys start with a letter or underscore, then letters, digits and underscores, up to 64 characters. At most 50 keys. Values are strings up to 1024 characters, numbers, booleans or null. This is the same shape as attributes on a token, and the same as update({ attributes }). Context comes from the browser, so treat it as a hint; put anything you rely on in the token.
Opening and showing
| Method | What it does |
|---|---|
open() | Opens the widget |
close() | Closes it |
toggle() | Opens it if closed, closes it if open |
showLauncher() | Shows the floating button |
hideLauncher() | Hides the floating button. The widget can still be opened from code |
showNewMessage(prefill?) | Opens a new conversation, with optional text in the message box |
showConversation(id) | Opens a conversation by ID, such as one from a conversationStarted event |
showSpace(space) | Opens 'home' or 'messages' (the conversation list) |
<button onclick="Ticketping('showNewMessage', 'I need help with my invoice')">Contact support</button>Calling open, toggle, showNewMessage, showConversation or showSpace before the widget has loaded makes it load right away instead of waiting for the browser to be idle. close, showLauncher and hideLauncher wait with the rest of the queue.
setLocale
Ticketping('setLocale', 'de')Changes the widget’s language and how it formats dates and times. Version 2.0 ships with English text only, so for now it mostly affects dates. Right-to-left locales get a right-to-left layout.
Reading state
These return values, so call them directly once the widget is ready:
| Method | Returns |
|---|---|
getUnreadCount() | The number of unread replies |
isOpen() | Whether the widget is open |
on and off
const stop = Ticketping.on('unreadCountChange', ({ count }) => {
document.title = count ? `(${count}) Acme` : 'Acme'
})
stop()This direct form needs the widget to be loaded, or the npm import. on returns a function that removes the handler, and off(event, handler) does the same. Before the widget loads, queue the handler with Ticketping('on', 'unreadCountChange', handler); that form doesn’t give you the function back, so remove it later with off.
| Event | Payload | When |
|---|---|---|
ready | none | The widget has loaded and is ready |
open | none | The widget opened |
close | none | The widget closed |
conversationStarted | { conversationId } | The visitor sent the first message of a new conversation |
messageSent | { conversationId, messageId } | The visitor sent a message |
messageReceived | { conversationId, messageId } | A reply arrived from your team or the AI agent |
unreadCountChange | { count } | The unread count changed |
identityChange | { state, userId } | state became anonymous, unverified or verified |
error | { code, message, details? } | Something went wrong. See below |
Errors
error events have a code you can check and a message for people. Common codes:
| Code | Meaning |
|---|---|
invalid_publishable_key | The key passed to init isn’t a pk_ key |
key_invalid | Ticketping doesn’t know the key. Copy it again from the dashboard |
origin_not_allowed | The site’s domain isn’t allowed for this widget. See allowed domains |
get_token_failed | getToken threw, or didn’t return a token |
token_invalid | Ticketping refused the token. details.reason says why |
verified_identity_required | The widget requires verified identity, and identify was called without getToken |
session_lost | The visitor’s session expired and couldn’t be renewed. The widget started over as an anonymous visitor |
rate_limited | Too many requests in a short time. The widget retries |
The widget also logs errors to the console with a [Ticketping] prefix.
trackEvent
Ticketping('trackEvent', 'checkout_started', { plan: 'pro' })The widget keeps recent events in memory only. Nothing is sent to Ticketping, so don’t use this for analytics.
preview
Ticketping('preview', { config, view: 'home' })Renders sample content with no network and no storage. view is launcher, home or thread. The dashboard’s live preview uses this. A host app doesn’t need it, and init is ignored while a preview is mounted.
destroy
Ticketping('destroy')Removes the widget from the page and removes every handler. Call init again to bring it back. Stored data stays, so the visitor keeps their conversations; use logout or consent('denied') to clear it.
Framework adapters
The React, Svelte and Vue adapters wrap the same API:
| Import | Use |
|---|---|
@ticketping/chat-widget/react | <TicketpingProvider publishableKey user getToken> and useTicketping() |
@ticketping/chat-widget/svelte | <Ticketping publishableKey user getToken /> |
@ticketping/chat-widget/vue | TicketpingPlugin and useTicketping() |
The React and Svelte user prop accepts id or userId (a string or a number). Vue has no user prop: call identify({ userId, getToken }) yourself.
useTicketping() in React returns unreadCount, isOpen, open(), close(), toggle(), showNewMessage(), showConversation(), showSpace(), update(), setContext(), trackEvent() and client. Other methods (logout, on, consent, …) are on that client. Importing Ticketping from @ticketping/chat-widget is a different instance and does not control the provider. Init options are read once; remount the provider to change them, or call update().
useTicketping() in Vue returns unreadCount and isOpen as numbers (not refs) plus every method on this page. In a template, read ticketping.unreadCount.
The Svelte component follows user the same way as React, and it does not export a store. Its instance is private, so Ticketping.open() from @ticketping/chat-widget does not control it.
The adapters ship with 2.0, so their exact names may still change in the betas. Check the package README for the version you installed. The methods on this page are stable.
Copy prompt for your AI coding agent
Use the Ticketping chat widget (v2) JavaScript API in this project.
Docs index: https://ticketping.com/llms.txt
This page as Markdown: https://ticketping.com/docs/widget-api.md
- Before the loader runs, use the queue stub window.Ticketping ||= (...args) => (Ticketping.q ||= []).push(args)
and call methods as Ticketping('method', ...args). With npm, import { Ticketping } from '@ticketping/chat-widget'.
- Call Ticketping('update') after client-side route changes.
- Use Ticketping('showNewMessage', text) for "Contact support" buttons, and hideLauncher if the app has its own button.
- Read return values (getUnreadCount, isOpen) only after the 'ready' event.
- Listen for 'error' events and log code and message.