JavaScript API
Every call goes through one function: Pong(method, ...args). Calls are queued until the loader is ready, so order and timing never matter.
Pong('openChat', true);
Pong('identify', { name: 'Jane Doe', email: 'jane@acme.com' });
Pong('on', 'message', (m) => console.log(m.type, m.text));
Visibility
| Method | What it does |
|---|---|
Pong('show') | Shows the chat button (after hide or startHidden). |
Pong('hide') | Hides the button and closes the chat. |
Pong('expandWidget') | Opens the chat window. |
Pong('minimizeWidget') | Closes the chat window, keeps the button. |
Pong('openChat', force) | Opens the chat window. With force = true it also shows a hidden button. |
// A "Contact support" link anywhere on the page
document.querySelector('#support').addEventListener('click', (e) => {
e.preventDefault();
Pong('openChat', true);
});
Who the visitor is
Pong('identify', data)
Attaches a name and email to the current visitor and shows them in the client card. Without a signature this is a hint: it labels the visitor but never merges their history with another device. To give a logged-in user the same chat on every device, pass a signed identity — see Verified identity.
Pong('identify', { name: 'Jane Doe', email: 'jane@acme.com' });
Pong('updateIntegrationData', data)
Any key/value pairs you want agents to see in the client card — plan, order number, account link. Values merge with what is already there; bursts within one second are sent together. The same data travels in webhooks as client.integrationData.
Pong('updateIntegrationData', {
plan: 'Pro',
orders: 12,
account: 'https://admin.acme.com/users/42',
});
Counters. A value { count: n } is a counter: the card shows its number in a bubble on the title's line. { add: n } changes it by n (negative to subtract), counting from the current value, or from 0 for a new key. Counters arrive in integrationData as { "count": n }.
Pong('updateIntegrationData', { cartItems: { count: 3 } });
Pong('updateIntegrationData', { cartItems: { add: 1 } }); // now 4
Keys that look like credentials (token, secret, password, and CSRF) are dropped on arrival. You can also set initial data before the loader runs with window.PongIntegration = { … }.
Anyone can call this from their browser console. To accept only the keys you expect, list them in Settings → Visitors (cart_* matches a prefix). The REST API is not limited by that list.
Pong('logout')
Call on sign-out. The browser gets a fresh anonymous visitor id and the widget reloads empty, so the next person at this computer does not see the previous user's chat.
Messages
Pong('sendAutoMessage', text)
Shows an automatic message in the visitor's chat — for example a greeting on the pricing page or a nudge after an error. It is stored in the conversation, so agents see what the visitor was shown.
if (location.pathname === '/pricing') {
Pong('sendAutoMessage', 'Questions about plans? We usually reply within a minute.');
}
trigger event to see which fired.Pong('setGroupId', id)
Routes the visitor to a group (team, department, language). The group id shows on the client card and in webhooks as client.groupId. Pass null to clear. You can also set it up front with PongSetup.groupId.
Debug log
Pong.debug(...) works like console.log, but the output appears in the agent's view of this chat, under Debug. Objects, arrays, errors with their stack and DOM elements are serialised safely (6 levels, 50 keys each).
try {
await checkout();
} catch (err) {
Pong.debug.error('checkout failed', err, { cart });
}
Pong.debug('flags', window.FEATURE_FLAGS);
Pong.debug.warn('slow response', ms);
Lifecycle
| Method | What it does |
|---|---|
Pong('pageView') | Reports the current URL and title as a page view. Only needed if your router does not use the History API. |
Pong('restart') | Reloads the widget frame and fires the restart event. |
Pong('kill') | Removes the widget from the page until the next full page load. |
State and events
Pong('getState') returns a snapshot (and passes it to a callback if you give one):
const s = Pong('getState');
// { ready, open, visible, clientId, verified, unread, lastAgentMessageAt, banned, call, groupId }
// call: null, or { state: 'incoming' | 'active', video } while an agent calls the visitor
Because the queue stub returns nothing before the loader is ready, prefer the callback form in code that may run early: Pong('getState', (s) => …).
Pong('on', name, handler) and Pong('off', name, handler?) subscribe to events — see Events.