Botsplash Dashboard Widget Integration Guide
Overview
The Botsplash Dashboard widget allows customers to embed the full Botsplash dashboard directly into their CRM or agent applications as an iframe widget. This enables agents to engage with customers without leaving their primary work environment.
Important Security Requirements
DOMAIN WHITELISTING IS REQUIRED: Before implementing the widget, your domain must be whitelisted by Botsplash for security reasons. Contact Botsplash support to whitelist your CRM domain.
Pre-whitelisted Domains
The following CRM platforms are already whitelisted and require no action:
- Salesforce
- HubSpot
- Other major CRM platforms (contact support for confirmation)
Production vs Staging Domains
| Environment | Domain | Example URL |
|---|---|---|
| Production | botsplash.com | https://acmemortgage.botsplash.com |
| Staging | botsplash.space | https://acmemortgage.botsplash.space |
When developing or testing against the Botsplash staging server, use the botsplash.space domain instead of botsplash.com. The script URL, BSPDASHBOARD_APP_URL, and any baseUrl overrides must all point to the .space domain for staging access.
X-Frame-Options Error
If you encounter an error message containing X-Frame-Options directive set to "sameorigin", this indicates your domain is not whitelisted. Please contact Botsplash support with your updated domain to resolve this issue. Also verify you are using the correct domain — botsplash.com for production and botsplash.space for staging.
Quick Start (Recommended)
The recommended approach is to use login() or loginAccount() with a server-generated JWT token. This provides secure, implicit authentication so agents don’t need to log in manually.
Step 1: Add the Widget Script
<script>
window.BSPDASHBOARD_APP_URL = 'https://<account-id>.botsplash.com';
window.BSPDASHBOARD_APP_HIDE_DEFAULT = true; // Prevent auto-load; we will call login() ourselves
(function () {
var d = document;
var s = d.createElement('script');
s.src = 'https://app.botsplash.com/y.js';
s.async = true;
d.getElementsByTagName('head')[0].appendChild(s);
})();
</script>
Step 2: Generate a JWT Token on Your Server
Your backend creates a signed JWT using the Botsplash API key. See Server-Side Token Generation for a full example.
Step 3: Log In with the Token
Once the script has loaded and you have a token from your server, call login() or loginAccount():
// Option A — login() with token and options
$bspdashboard.login(token, {
version : 2, // Default: 1
displayType : window.$bspdashboard.DisplayType.Floating, // Optional
uiOptions : window.$bspdashboard.WidgetUiOptions.HideAll, // Optional
});
// Option B — loginAccount() convenience function
$bspdashboard.loginAccount('<account-id>', token, {
version : 2,
displayType : window.$bspdashboard.DisplayType.Floating,
uiOptions : window.$bspdashboard.WidgetUiOptions.HideAll,
});
Replace <account-id> with your actual Botsplash account identifier (e.g. acmemortgage).
Global API Reference (window.$bspdashboard)
The widget script exposes a global $bspdashboard object with the following methods and constants.
Constants
| Constant | Values | Description |
|---|---|---|
DisplayType.Floating | 1 | Floating overlay (default) |
DisplayType.Inline | 4 | Inline / embedded in a container |
WidgetUiOptions.None | 0 | Show all UI sections (default) |
WidgetUiOptions.HideProfile | 1 | Hide the profile section |
WidgetUiOptions.HideSettings | 2 | Hide the settings section |
WidgetUiOptions.HideAll | 3 | Hide both profile and settings |
Methods
login(tokenOrWidgetUrl, options)
Primary authentication method. Accepts either a JWT token or a full widget URL.
Parameters:
| Parameter | Type | Description |
|---|---|---|
tokenOrWidgetUrl | string | A JWT token or a full https://... widget URL |
options | object | Optional configuration (see below) |
Options object:
| Property | Type | Default | Description |
|---|---|---|---|
accountName | string | Extracted from hostname | Account identifier (e.g. 'acmemortgage') |
baseUrl | string | BSPDASHBOARD_APP_URL or https://{accountName}.botsplash.com | Override the base URL used to build the widget login URL |
version | number | 1 | Widget protocol version. Use 2 for current server compatibility |
rootId | string | 'bspdashboard-root' | DOM element ID where the widget mounts |
displayType | number | 1 (Floating) | Widget display mode — see DisplayType constants |
uiOptions | number | 0 (None) | Bitwise UI visibility flags — see WidgetUiOptions constants |
Examples:
// Token-based login with inline display, hiding profile & settings
$bspdashboard.login(token, {
accountName : 'acmemortgage',
version : 2,
displayType : window.$bspdashboard.DisplayType.Floating,
uiOptions : window.$bspdashboard.WidgetUiOptions.HideAll,
});
loginAccount(accountName, token, optionsOrDevUrl, maybeOptions)
Convenience wrapper around login() that takes the account name as a separate argument.
Parameters:
| Parameter | Type | Description |
|---|---|---|
accountName | string | Account identifier (e.g. 'acmemortgage') |
token | string | JWT authentication token |
optionsOrDevUrl | object or string | Options object or a dev base URL string |
maybeOptions | object | Options object (only used when the third argument is a URL string) |
Examples:
// Standard usage with options
$bspdashboard.loginAccount('acmemortgage', token, {
version : 2,
displayType : window.$bspdashboard.DisplayType.Floating,
uiOptions : window.$bspdashboard.WidgetUiOptions.HideAll,
});
// Dev / staging usage with a base URL override
$bspdashboard.loginAccount('acmemortgage', token, 'https://acmemortgage.botsplash.space', {
version : 2,
displayType : window.$bspdashboard.DisplayType.Floating,
uiOptions : window.$bspdashboard.WidgetUiOptions.HideAll,
});
openChat()
Opens the dashboard widget window. Useful for programmatically showing the chat frame in response to user actions (e.g. clicking a “Chat” button in your CRM).
$bspdashboard.openChat();
closeChat()
Closes the dashboard widget window without destroying it. The widget stays loaded and can be reopened with openChat().
$bspdashboard.closeChat();
loadVisitor(visitor)
Loads an existing visitor by clientVisitorId, or creates a new visitor when one does not yet exist. This is the primary method for linking CRM customer records to Botsplash conversations.
Parameters:
| Parameter | Type | Description |
|---|---|---|
visitor | object | Visitor information (see fields below) |
Visitor object fields:
| Field | Type | Required | Description |
|---|---|---|---|
clientVisitorId | string | No | Your CRM’s unique customer ID. When provided, Botsplash looks up the existing visitor. When omitted, a new visitor is created |
agentClientUserId | string | No | Agent ID to assign the conversation to |
participantAgentIds | string[] | No | Additional agent IDs to add as participants |
teamCode | string | No | Team code to route the conversation to |
firstName | string | No | Visitor’s first name |
lastName | string | No | Visitor’s last name |
email | string | No | Visitor’s email address |
phoneNumber | string | No | Visitor’s phone number |
state | string | No | Visitor’s state / region |
tzName | string | No | Visitor’s timezone (IANA format, e.g. 'America/New_York') |
deliveryStatus | number | No | Delivery status code |
extendedAttributes | object | No | Custom key-value pairs for additional visitor data |
Examples:
// Load an existing visitor by CRM customer ID
$bspdashboard.loadVisitor({
clientVisitorId : '12345',
});
// Load a visitor with full profile information
$bspdashboard.loadVisitor({
clientVisitorId : '12345',
agentClientUserId : '12345',
participantAgentIds: ['54321'],
teamCode : '333',
firstName : 'Jane',
lastName : 'Doe',
email : 'example@example.com',
phoneNumber : '3334445555',
state : 'NC',
tzName : 'America/New_York',
deliveryStatus : 202,
extendedAttributes : {
color : 'red',
leadSourceId : '123456789',
priority : 'high',
},
});
// Create a new visitor (no clientVisitorId)
$bspdashboard.loadVisitor({
firstName : 'John',
lastName : 'Smith',
email : 'john.smith@example.com',
phoneNumber : '5551234567',
});
logoff()
Triggers a logout event inside the widget iframe.
$bspdashboard.logoff();
Server-Side Token Generation
Your backend must generate a signed JWT that the widget uses for implicit authentication. The token is signed with your Botsplash API key using the HS256 algorithm.
JWT Payload Fields
| Field | Type | Required | Description |
|---|---|---|---|
said | string | No | Sub-account identifier (for multi-location setups) |
id | string | Yes | Unique user ID in your system |
fn | string | Yes | User’s first name |
ln | string | Yes | User’s last name |
email | string | Yes | User’s email address |
source | string | No | Identifier for the calling application (e.g. 'acme-center') |
iat | number | Yes | Issued-at timestamp (seconds since epoch) |
Example: Express.js + jsonwebtoken
/* Copyright (c) 2016-present Rohi LLC. All rights reserved. */
const express = require('express');
const jwt = require('jsonwebtoken');
const router = express.Router();
// POST /api/botsplash/token
router.post('/token', async (req, res) => {
try {
const userId = req.user.id; // From your auth middleware
const botsplashApiKey = process.env.BOTSPLASH_API_KEY;
if (!botsplashApiKey) {
return res.status(500).json({ error: 'Botsplash API key not configured' });
}
const profile = await getUserProfile(userId);
if (!profile) {
return res.status(404).json({ error: 'Profile not found' });
}
const payload = {
said : profile.subAccountId, // Optional: for multi-location setups
id : userId,
fn : profile.firstName,
ln : profile.lastName,
email : profile.email,
source : 'integration-partner-name',
iat : Math.floor(Date.now() / 1000),
};
const token = jwt.sign(payload, botsplashApiKey, { algorithm: 'HS256' });
return res.json({
success : true,
token,
accountName : process.env.BOTSPLASH_ACCOUNT_NAME, // e.g. 'acmemortgage'
});
} catch (err) {
console.error('botsplash:token:error:', err);
return res.status(500).json({ error: 'Failed to generate token' });
}
});
module.exports = router;
Client-Side Integration Examples
Simple Example: Static HTML Page
A minimal integration that loads the widget script, fetches a token from your server, and calls loginAccount().
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Agent Dashboard</title>
<style>
#bsp-main {
width: 100%;
height: 100vh;
}
</style>
</head>
<body>
<div id="bsp-main"></div>
<script>
var BSP_APP_URL = 'https://acmemortgage.botsplash.com';
var BSP_ACCOUNT_ID = 'acmemortgage';
window.BSPDASHBOARD_APP_URL = BSP_APP_URL;
window.BSPDASHBOARD_APP_HIDE_DEFAULT = true;
(function () {
var d = document;
var s = d.createElement('script');
s.src = BSP_APP_URL + '/y.js';
s.async = true;
s.onload = function () {
// Fetch token from your server, then log in
fetch('/api/botsplash/token', { method: 'POST' })
.then(function (r) { return r.json(); })
.then(function (data) {
if (data.token && window.$bspdashboard) {
window.$bspdashboard.loginAccount(BSP_ACCOUNT_ID, data.token, {
rootId : 'bsp-main',
version : 2,
displayType : window.$bspdashboard.DisplayType.Floating,
uiOptions : window.$bspdashboard.WidgetUiOptions.HideAll,
});
}
});
};
d.getElementsByTagName('head')[0].appendChild(s);
})();
</script>
</body>
</html>
Robust Example: React SPA with BotsplashProvider
For single-page applications the widget script only needs to be loaded once. A React context provider handles authentication state changes, loading the script on login and cleaning up on logout.
TypeScript Declarations
Add these type declarations to your project (e.g. in src/types/botsplash.d.ts or inline):
declare global {
interface Window {
BSPDASHBOARD_APP_URL?: string;
BSPDASHBOARD_APP_HIDE_DEFAULT?: boolean;
$bspdashboard?: {
login: (tokenOrUrl: string, options?: any) => void;
loginAccount: (accountName: string, token: string, options?: any) => void;
logoff: () => void;
load: (forceReload?: boolean, clientVisitorId?: string, widgetUrl?: string) => void;
remove: (shouldLogout?: boolean) => void;
setUser: (id: string, widgetUrl?: string, options?: any) => void;
loadVisitor: (visitorData: {
firstName?: string;
lastName?: string;
email?: string;
phoneNumber?: string;
clientVisitorId?: string;
agentClientUserId?: string;
state?: string;
extendedAttributes?: Record<string, any>;
}) => void;
DisplayType: Record<string, number>;
WidgetUiOptions: Record<string, number>;
};
}
}
BotsplashWidget Component
A self-contained component you can drop into any page. The parent passes isLoggedIn and a fetchToken callback, so the component has no dependency on any specific auth library or API client.
import { useEffect, useState, useRef } from 'react';
const BSP_APP_URL = import.meta.env.VITE_BSP_APP_URL || 'https://acmemortgage.botsplash.com';
interface BotsplashWidgetProps {
isLoggedIn : boolean;
fetchToken : () => Promise<{ accountName: string; token: string } | null>;
}
const BotsplashWidget = ({ isLoggedIn, fetchToken }: BotsplashWidgetProps) => {
const [isWidgetLoaded, setIsWidgetLoaded] = useState(false);
const prevLoggedIn = useRef<boolean | null>(null);
useEffect(() => {
// Only act on actual auth state changes
if (prevLoggedIn.current === isLoggedIn) { return; }
prevLoggedIn.current = isLoggedIn;
const loadWidget = async () => {
if (isLoggedIn && !isWidgetLoaded) {
// Fetch a signed token from the parent's callback
let tokenInfo;
try {
tokenInfo = await fetchToken();
} catch (err) {
console.error('Failed to generate Botsplash token:', err);
return;
}
if (!tokenInfo?.token) { return; }
window.BSPDASHBOARD_APP_URL = BSP_APP_URL;
window.BSPDASHBOARD_APP_HIDE_DEFAULT = true;
const loginOptions = {
rootId : 'bsp-main',
version : 2,
displayType : window.$bspdashboard.DisplayType.Floating,
uiOptions : window.$bspdashboard.WidgetUiOptions.HideAll,
};
if (window.$bspdashboard) {
// SPA navigation: script already loaded from a previous mount
window.$bspdashboard.loginAccount(
tokenInfo.accountName, tokenInfo.token, loginOptions
);
} else {
// First load: inject the script tag once
const script = document.createElement('script');
script.src = `${BSP_APP_URL}/y.js`;
script.async = true;
script.onload = () => {
if (window.$bspdashboard) {
window.$bspdashboard.loginAccount(
tokenInfo.accountName, tokenInfo.token, loginOptions
);
}
};
document.head.appendChild(script);
}
setIsWidgetLoaded(true);
} else if (!isLoggedIn && isWidgetLoaded) {
// User logged out — tear down the widget
if (window.$bspdashboard) {
window.$bspdashboard.remove(true);
}
setIsWidgetLoaded(false);
}
};
loadWidget();
}, [isLoggedIn, isWidgetLoaded, fetchToken]);
// Cleanup on unmount
useEffect(() => {
return () => {
if (window.$bspdashboard) {
window.$bspdashboard.remove(true);
}
};
}, []);
return <div id="bsp-main" style= />;
};
export default BotsplashWidget;
Using the Component
The parent owns the auth state and token-fetching logic, then passes them as props:
import { useCallback } from 'react';
import { useAuth } from './hooks/useAuth';
import { api } from './lib/api-client';
import BotsplashWidget from './components/BotsplashWidget';
function Dashboard() {
const { user } = useAuth();
const fetchToken = useCallback(async () => {
return api.botsplash.generateToken();
}, []);
return (
<div style=>
<h1>Agent Dashboard</h1>
<BotsplashWidget isLoggedIn={!!user} fetchToken={fetchToken} />
</div>
);
}
Or at the top level for a floating widget on every page:
import { useCallback } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { useAuth } from './hooks/useAuth';
import { api } from './lib/api-client';
import Dashboard from './pages/Dashboard';
import BotsplashWidget from './components/BotsplashWidget';
function AppContent() {
const { user } = useAuth();
const fetchToken = useCallback(async () => {
return api.botsplash.generateToken();
}, []);
return (
<>
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
</Routes>
<BotsplashWidget isLoggedIn={!!user} fetchToken={fetchToken} />
</>
);
}
const App = () => (
<BrowserRouter>
<AppContent />
</BrowserRouter>
);
Loading a Specific Visitor
After the widget is loaded, you can load a specific visitor’s conversation:
$bspdashboard.loadVisitor({
clientVisitorId : 'CRM_CUSTOMER_ID',
});
Configuration Reference
Global Variables
| Variable | Type | Description |
|---|---|---|
window.BSPDASHBOARD_APP_URL | string | Your Botsplash account URL (e.g. 'https://acmemortgage.botsplash.com') |
window.BSPDASHBOARD_APP_HIDE_DEFAULT | boolean | Set to true to prevent the widget from auto-loading on script init. Required when using login() / loginAccount() |
window.BSPDASHBOARD_CLIENT_VISITOR_ID | string | Pre-set a visitor ID to load automatically (only used when auto-load is enabled) |
Troubleshooting
Common Issues
- X-Frame-Options Error
- Cause: Domain not whitelisted
- Solution: Contact Botsplash support to whitelist your domain
- Widget Not Loading
- Cause: Incorrect account ID or script URL
- Solution: Verify your account ID and script URL match
bspdashboard:login:invalidargsin Console- Cause: Missing account name or token in
login()/loginAccount()call - Solution: Ensure both the account name and a valid JWT token are provided
- Cause: Missing account name or token in
- Widget Shows Inside an Iframe
- Cause: The host page itself is loaded inside an iframe
- Solution: The widget does not support nested iframe embedding. Load the host page directly
- Script Loading Issues
- Cause: Network restrictions or CORS policies
- Solution: Check the browser console for errors and verify network access
Support and Contact
For technical support, domain whitelisting requests, or feature questions:
- Contact the Botsplash support team
- Provide your account ID and domain information
- Include any error messages or browser console logs