Chat Widget SDK
Complete reference for the Transactional Support Chat Widget SDK
Chat Widget SDK
The Transactional Support Chat Widget provides a complete live chat experience for your website. This document covers all SDK methods, configuration options, and best practices.
Installation
Get the embed code from your inbox settings:
- Go to Support > Inboxes > Your Inbox > Settings
- Enable the Chat Widget toggle
- Copy the embed code from the Embed Code section
Add the copied script before the closing </body> tag:
<!-- Transactional Support Widget -->
<script>
(function(w,d,s,o,n,f,js,fjs){
w[o]=w[o]||{};w[o][n]=w[o][n]||function(){(w[o][n].q=w[o][n].q||[]).push(arguments)};
w[o][n].l=1*new Date();js=d.createElement(s);fjs=d.getElementsByTagName(s)[0];
js.id=o+'_'+n;js.src=f;js.async=1;fjs.parentNode.insertBefore(js,fjs);
}(window,document,'script','Transactional','support','https://cdn.usetransactional.com/sdk/support.min.js'));
Transactional.support('init', { inboxId: 'YOUR_INBOX_ID' });
</script>Replace YOUR_INBOX_ID with your inbox ID from the settings page.
SDK Methods Reference
init(options)
Initialize the chat widget with your inbox configuration.
Transactional.support('init', {
inboxId: 'YOUR_INBOX_ID', // Required - from inbox settings
// Optional: Behavior
defaultState: 'closed', // 'open' | 'closed' | 'hidden'
soundEnabled: true
});Init Options Reference:
| Option | Type | Default | Description |
|---|---|---|---|
inboxId | string | Required | Your inbox ID from settings |
defaultState | string | closed | Initial widget state (see below) |
soundEnabled | boolean | true | Enable notification sounds |
Default State Options:
| Value | Description |
|---|---|
closed | Shows launcher button only (default) |
open | Widget opens automatically on page load |
hidden | Widget is completely hidden until triggered via show() |
The defaultState option can also be configured in the dashboard under Inbox Settings > Chat Widget > Default State. Client-side options override server configuration.
identify(userId, userData)
Identify a visitor as a known user. Call this when a user logs in.
Transactional.support('identify', 'user-123', {
// Required
email: 'john@example.com',
// Recommended
name: 'John Doe',
// Optional standard fields
phone: '+1234567890',
avatarUrl: 'https://example.com/avatar.jpg',
// Custom attributes (any key-value pairs)
plan: 'premium',
role: 'admin',
lifetime_value: 5000,
signup_date: '2024-01-01'
});Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
userId | string | Yes | Unique user ID from your system |
userData | object | No | User data and custom attributes |
Standard User Fields:
| Field | Type | Description |
|---|---|---|
email | string | User's email address |
name | string | Display name |
phone | string | Phone number |
avatarUrl | string | Profile image URL |
Any additional fields are stored as custom attributes and displayed in the dashboard.
company(companyId, companyData)
Associate the current user with a company. Useful for B2B support.
Transactional.support('company', 'company-456', {
// Required
name: 'Acme Inc',
// Optional standard fields
website: 'https://acme.com',
industry: 'Technology',
size: '100-500',
plan: 'enterprise',
// Custom attributes
mrr: 5000,
contract_end: '2025-01-01',
account_manager: 'Jane Smith',
features: ['analytics', 'api', 'sso']
});Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
companyId | string | Yes | Unique company ID from your system |
companyData | object | No | Company data and custom attributes |
Standard Company Fields:
| Field | Type | Description |
|---|---|---|
name | string | Company name |
website | string | Company website |
industry | string | Industry category |
size | string | Company size range |
plan | string | Subscription plan |
trackEvent(eventName, properties)
Track a custom event for the current user. Events appear in the visitor's activity timeline.
// Simple event
Transactional.support('trackEvent', 'page_viewed');
// Event with properties
Transactional.support('trackEvent', 'purchase_completed', {
orderId: 'order-123',
amount: 99.99,
currency: 'USD',
products: ['Product A', 'Product B']
});
// Feature usage tracking
Transactional.support('trackEvent', 'feature_used', {
feature: 'data_export',
format: 'csv',
rows_exported: 1500
});Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
eventName | string | Yes | Event name (snake_case recommended) |
properties | object | No | Additional event data |
trackPageView()
Track a page view for the current user. Page views are automatically tracked on initial load and browser navigation, but you can manually trigger them for SPAs.
// Manual page view (for SPAs)
Transactional.support('trackPageView');Automatic Tracking:
- Page views are automatically tracked when the widget loads
- Navigation via
pushStateandpopstateis automatically detected - Duplicate page views to the same URL are deduplicated
show()
Show the chat widget (messenger window).
Transactional.support('show');Opens the messenger window. If the widget was initialized with defaultState: 'hidden', this will make both the launcher and messenger visible.
hide()
Hide the chat widget (messenger window).
Transactional.support('hide');Closes the messenger window. The launcher button remains visible (unless widget is in hidden mode).
toggle()
Toggle the messenger visibility.
Transactional.support('toggle');If open, closes it. If closed, opens it.
shutdown()
Completely remove the widget from the page.
Transactional.support('shutdown');Use this when:
- User logs out
- Navigating to a page where widget shouldn't appear
- Single-page app cleanup
Important: After shutdown, you must call init() again to re-initialize.
on(event, callback)
Register an event listener.
// Listen for widget open
Transactional.support('on', 'show', () => {
console.log('Widget opened');
});
// Listen for widget close
Transactional.support('on', 'hide', () => {
console.log('Widget closed');
});
// Listen for unread count changes
Transactional.support('on', 'unreadCountChange', (count) => {
console.log('Unread messages:', count);
// Update your app's notification badge
updateBadge(count);
});Available Events:
| Event | Callback Args | Description |
|---|---|---|
show | none | Widget messenger opened |
hide | none | Widget messenger closed |
unreadCountChange | count: number | Unread message count changed |
off(event, callback)
Remove an event listener.
const myCallback = () => console.log('Widget opened');
// Add listener
Transactional.support('on', 'show', myCallback);
// Remove listener
Transactional.support('off', 'show', myCallback);Complete Examples
Basic Integration
Copy the embed code from your inbox settings and add it before </body>:
<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<!-- Your app content -->
<!-- Transactional Support Widget -->
<script>
(function(w,d,s,o,n,f,js,fjs){
w[o]=w[o]||{};w[o][n]=w[o][n]||function(){(w[o][n].q=w[o][n].q||[]).push(arguments)};
w[o][n].l=1*new Date();js=d.createElement(s);fjs=d.getElementsByTagName(s)[0];
js.id=o+'_'+n;js.src=f;js.async=1;fjs.parentNode.insertBefore(js,fjs);
}(window,document,'script','Transactional','support','https://cdn.usetransactional.com/sdk/support.min.js'));
Transactional.support('init', { inboxId: 'YOUR_INBOX_ID' });
</script>
</body>
</html>With User Authentication
// When user logs in
function onUserLogin(user) {
Transactional.support('identify', user.id, {
email: user.email,
name: user.name,
plan: user.subscription.plan
});
if (user.company) {
Transactional.support('company', user.company.id, {
name: user.company.name,
plan: user.company.plan
});
}
}
// When user logs out
function onUserLogout() {
Transactional.support('shutdown');
// Re-initialize for anonymous visitors
Transactional.support('init', { inboxId: 'YOUR_INBOX_ID' });
}React / Next.js Integration
'use client';
import { useEffect } from 'react';
import { useUser } from './hooks/useUser';
declare global {
interface Window {
Transactional: {
support: (command: string, ...args: unknown[]) => void;
};
}
}
export function SupportWidget() {
const { user, isAuthenticated } = useUser();
// Initialize widget
useEffect(() => {
// Load SDK
(function(w,d,s,o,n,f,js,fjs){
w[o]=w[o]||{};w[o][n]=w[o][n]||function(){(w[o][n].q=w[o][n].q||[]).push(arguments)};
w[o][n].l=1*new Date();js=d.createElement(s);fjs=d.getElementsByTagName(s)[0];
js.id=o+'_'+n;js.src=f;js.async=1;fjs.parentNode.insertBefore(js,fjs);
}(window,document,'script','Transactional','support','https://cdn.usetransactional.com/sdk/support.min.js'));
window.Transactional.support('init', {
inboxId: process.env.NEXT_PUBLIC_SUPPORT_INBOX_ID
});
return () => {
window.Transactional?.support?.('shutdown');
};
}, []);
// Identify user when authenticated
useEffect(() => {
if (isAuthenticated && user) {
window.Transactional.support('identify', user.id, {
email: user.email,
name: user.name,
plan: user.plan
});
}
}, [isAuthenticated, user]);
return null;
}Vue Integration
<script setup lang="ts">
import { onMounted, onUnmounted, watch } from 'vue';
import { useUserStore } from './stores/user';
declare global {
interface Window {
Transactional: {
support: (command: string, ...args: unknown[]) => void;
};
}
}
const userStore = useUserStore();
onMounted(() => {
// Load SDK
(function(w,d,s,o,n,f,js,fjs){
w[o]=w[o]||{};w[o][n]=w[o][n]||function(){(w[o][n].q=w[o][n].q||[]).push(arguments)};
w[o][n].l=1*new Date();js=d.createElement(s);fjs=d.getElementsByTagName(s)[0];
js.id=o+'_'+n;js.src=f;js.async=1;fjs.parentNode.insertBefore(js,fjs);
}(window,document,'script','Transactional','support','https://cdn.usetransactional.com/sdk/support.min.js'));
window.Transactional.support('init', {
inboxId: import.meta.env.VITE_SUPPORT_INBOX_ID
});
});
// Watch for auth changes
watch(() => userStore.user, (user) => {
if (user) {
window.Transactional.support('identify', user.id, {
email: user.email,
name: user.name
});
}
}, { immediate: true });
onUnmounted(() => {
window.Transactional?.support?.('shutdown');
});
</script>Contextual Help
// Open widget with context when user clicks help button
function openContextualHelp(topic) {
Transactional.support('show');
Transactional.support('trackEvent', 'help_requested', { topic });
}Hidden Widget with Custom Trigger
Use defaultState: 'hidden' when you want full control over when the widget appears:
// Initialize widget in hidden mode
Transactional.support('init', {
inboxId: 'YOUR_INBOX_ID',
defaultState: 'hidden'
});
// Custom "Help" button in your app
document.getElementById('help-button').addEventListener('click', () => {
Transactional.support('show');
});
// Or trigger based on user frustration signals
let errorCount = 0;
window.addEventListener('error', () => {
errorCount++;
if (errorCount >= 3) {
Transactional.support('show');
Transactional.support('trackEvent', 'help_offered_after_errors', {
errorCount
});
}
});Using Multiple Transactional SDKs
If you're using multiple Transactional products (Support, Forms, Auth), each SDK uses its own namespace:
<!-- Support Widget -->
<script>
(function(w,d,s,o,n,f,js,fjs){
w[o]=w[o]||{};w[o][n]=w[o][n]||function(){(w[o][n].q=w[o][n].q||[]).push(arguments)};
w[o][n].l=1*new Date();js=d.createElement(s);fjs=d.getElementsByTagName(s)[0];
js.id=o+'_'+n;js.src=f;js.async=1;fjs.parentNode.insertBefore(js,fjs);
}(window,document,'script','Transactional','support','https://cdn.usetransactional.com/sdk/support.min.js'));
Transactional.support('init', { inboxId: 'YOUR_INBOX_ID' });
</script>
<!-- Forms SDK (when available) -->
<script>
(function(w,d,s,o,n,f,js,fjs){
w[o]=w[o]||{};w[o][n]=w[o][n]||function(){(w[o][n].q=w[o][n].q||[]).push(arguments)};
w[o][n].l=1*new Date();js=d.createElement(s);fjs=d.getElementsByTagName(s)[0];
js.id=o+'_'+n;js.src=f;js.async=1;fjs.parentNode.insertBefore(js,fjs);
}(window,document,'script','Transactional','forms','https://cdn.usetransactional.com/sdk/forms.min.js'));
Transactional.forms('embed', { formId: 'YOUR_FORM_ID', container: '#form' });
</script>All SDKs share the same Transactional global object but use separate namespaces. Identity set via Transactional.support('identify', ...) is automatically shared with other SDKs.
Environment Variables
Add these to your environment file:
# Get your inbox ID from the inbox settings page
NEXT_PUBLIC_SUPPORT_INBOX_ID=your-inbox-idTroubleshooting
Widget Not Appearing
- Check inbox ID is correct
- Verify script is loaded (Network tab)
- Check console for errors
- Ensure CSP allows the script domain
User Not Being Identified
- Verify
identifyis called afterinit - Check user ID is a string
- Confirm user data format
Events Not Tracking
- Ensure widget is initialized
- Check event name is a string
- Verify network requests succeed
Messages Not Sending
- Check WebSocket connection
- Verify inbox is active
- Check for rate limiting
Next Steps
- Quick Start - Get started quickly
- Visitors - Visitor tracking
- Companies - Company management
- API Reference - Full API docs
On This Page
- Installation
- SDK Methods Reference
- init(options)
- identify(userId, userData)
- company(companyId, companyData)
- trackEvent(eventName, properties)
- trackPageView()
- show()
- hide()
- toggle()
- shutdown()
- on(event, callback)
- off(event, callback)
- Complete Examples
- Basic Integration
- With User Authentication
- React / Next.js Integration
- Vue Integration
- Contextual Help
- Hidden Widget with Custom Trigger
- Using Multiple Transactional SDKs
- Environment Variables
- Troubleshooting
- Widget Not Appearing
- User Not Being Identified
- Events Not Tracking
- Messages Not Sending
- Next Steps