The headless web SDK gives you the flexibility to extend and customize your company's support experience according to your needs. It contains all our familiar web SDK features and provides the ability to build out the UI and UX to support them.
In the context of software development, "headless" refers to a decoupled architecture where the frontend presentation layer (the "head") is separated from the backend logic and capabilities. In a headless architecture the backend, also known as the "headless" part, provides APIs that let you use its features and services.
An example is custom workflow automation. When an end-user initiates a chat, the
on("chat.message")
event is triggered. You can define custom
automation triggers based on specific chat messages you've received. For example, if an end-user
types "Escalate" in the chat, the event handler can automatically escalate the
chat session to a higher-level support team, ensuring prompt attention to
critical issues.
This guide walks you through the SDK's installation process, integration capabilities, and usage. For details about using the API, see the Headless web SDK API documentation. A list of available events can be found on the events page.
Install the headless web SDK
To install the headless web SDK, use the following code snippet in your project:
npm install @ujet/websdk-headless --save
Use the headless web SDK
Example:
import { Client } from "@ujet/websdk-headless"
const host = "Your Google CCaaS host";
const companyId = "Your company ID";
async function authenticate() {
const resp = await fetch("/your-auth-endpoint")
const data = await resp.json()
return { token: data.token }
}
// create the headless web SDK client instance
const client = new Client({
companyId: companyId,
host: host,
authenticate: authenticate,
})
// const company = await client.getCompany()
// const menus = await client.getMenus()
function startChat() {
// Create a new chat session
client.createChat(menuId, {
lang: 'en', // Example: Set language to English
custom_data: {
unsigned: {
myData: 'data',
browser: 'Chrome'
}
}
})
.then((chat) => {
// Chat has started
console.log("Chat started");
// ... do things where
})
.catch(error => {
console.error("Error creating chat:", error);
});
}
// ***** Headless SDK event handlers
// Handlingchat connected event
client.on("chat.connected", () => {
console.log("Chat connected");
const messages = client.fetchMessages()
.then((messages) => {
console.log(messages);
})
});
// Handlingchat disconnected event
client.on("chat.disconnected", () => {
console.log("Chat disconnected");
});
// Handling chat timedout event
client.on("chat.timeout", () => {
console.log("Chat timedout");
});
// Handling chat destroyed event
client.on("chat.destroyed", () => {
console.log("Chat destroyed");
});
// Handlingchat end event
client.on("chat.ended", () => {
console.log("Chat ended");
});
// Handlingchat dismissed event
client.on("chat.dismissed", () => {
console.log("Chat dismissed");
});
// Handling Member joined events
client.on("chat.memberJoined", (identity) => {
console.log(`Member joined: ${identity}`);
});
// Handling Member left events
client.on("chat.memberLeft", (identity) => {
console.log(`Member left: ${identity}`);
});
// Handling chat ongoing
client.on("chat.ongoing", (chat) => {
console.log(`Chat ongoing: ${chat.state.id} - ${chat.state.status_text}`);
});
// Handling chat updated
client.on("chat.updated", (chat) => {
console.log(`Chat updated: ${chat.state.id} - ${chat.state.status_text}`);
});
// Listen for incoming messages
client.on("chat.message", (message) => {
console.log(`Message received ${JSON.stringify(message)}`);
});
// Handling typing started:
client.on("chat.typingStarted", () => {
console.log("Chat typing started");
});
// Handling typing ended:
client.on("chat.typingEnded", () => {
console.log("Chat typing ended");
});
// Call initChat() after the client is ready
client.on("ready", () => {
console.log("Client ready");
// create chat as soon as SDK is ready
// alternativly this could be started when the user selects a button
startChat();
});
The Client
class accepts several options (you can customize them according to
your requirements):
interface ClientOption {
companyId: string;
authenticate: () => Promise<TokenResponse>;
tenant?: string;
host?: string;
lang?: string;
bridge?: string;
cobrowse?: {
enabled: boolean;
messages?: CobrowseMessages;
api?: string;
license?: string;
trustedOrigins?: string[];
capabilities?: string[];
registration?: boolean;
redactedViews?: string[];
unredactedViews?: string[];
};
}
Enable logging
During implementation and testing it might be necessary to gather additional
information in the console log. To enable logging for the headless SDK, import
Logger
and consoleLoggerHandler
by adding the following code to your web application:
import {Logger, consoleLoggerHandler } from '@ujet/websdk-headless'
Logger.addHandler(consoleLoggerHandler)
Enable co-browse
The headless web SDK offers a built-in integration with Co-browse. The SDK provides a default UI, but you can customize it by providing your own CSS or styling it.
The default template is:
<dialog open class="cobrowse-dialog">
<h1>$title</h1>
<div class="cobrowse-dialog_content">$content</div>
<div class="cobrowse-dialog_footer">
<button class="cobrowse-dialog_allow js-cobrowse-allow">$allow</button>
<button class="cobrowse-dialog_deny js-cobrowse-deny">$deny</button>
</div>
</dialog>
The template is wrapped by a <div>
tag:
<div class="cobrowse-wrapper">${template}</div>
You can add CSS style according to the previous template's class names.
Custom template
You can also provide a custom template with class="cobrowse-template"
, for
example:
const COBROWSE_CONSENT_TEMPLATE = '
<script class="cobrowse-template" type="text/template">
<div class="cobrowse">
<div class="cobrowse-title">$title</div>
<div class="cobrowse-content">$content</div>
<div class="cobrowse-footer">
<button class="cobrowse-deny js-cobrowse-deny">$deny</button>
<button class="cobrowse-allow js-cobrowse-allow">$allow</button>
</div>
</div>
</script>
'
const client = new Client({
companyId: "YOUR-COMPANY-ID",
tenant: "YOUR-TENANT-NAME",
authenticate: authenticate,
cobrowse: {
template: COBROWSE_CONSENT_TEMPLATE,
...
},
...
})
Variables $title
, $content
, $deny
, and $allow
will be replaced
automatically.
Custom messages
The default messages for the $title
, $content
, $deny
, and $allow
variables are:
{
"confirmSessionTitle": "Co-browse Session Request",
"confirmSessionContent": "Do you want to share your current screen with the agent?",
"endSessionText": "End Co-browse Session",
"confirmRemoteControlTitle": "Remote Access Request",
"confirmRemoteControlContent": "The agent would like to have access to your currently shared screen to further assist you. Do you want to allow this?",
"confirmFullDeviceTitle": "Screen Share Request",
"confirmFullDeviceContent": "Do you want to share your full screen with the agent? The agent will not be able to control anything on the screen.",
"allowText": "Allow",
"denyText": "Deny"
}
You can customize the message using cobrowse.messages
:
const client = new Client({
companyId: "YOUR-COMPANY-ID",
tenant: "YOUR-TENANT-NAME",
authenticate: authenticate,
cobrowse: {
enabled: true,
messages: {
confirmSessionTitle: "...",
confirmSessionContent: "...",
endSessionText: "...",
confirmRemoteControlTitle: "...",
confirmRemoteControlContent: "...",
confirmFullDeviceTitle: "...",
confirmFullDeviceContent: "...",
allowText: "...",
denyText: "...",
}
}
})