This guide explains how to embed the Soliplex Chat widget into any website.
Add the following to your HTML page:
<script src="https://your-domain.com/soliplex-chat.js"></script>
<script>
SoliplexChat.init({
baseUrl: "https://my-server.example.com"
});
</script>That's it! A chat bubble will appear in the bottom-right corner of your page. When clicked, users will see a list of available chat rooms to choose from.
If you omit baseUrl, the widget will prompt the user to enter a server URL when opened:
<script>
SoliplexChat.init({
title: "Connect to Chat"
});
</script>| Option | Type | Default | Description |
|---|---|---|---|
baseUrl |
string | undefined |
Backend API URL. If omitted, the widget prompts the user for a server URL |
roomIds |
string[] | [] |
Room IDs to show; empty or omit to show all available rooms |
autoHideSeconds |
number | 0 |
Seconds until bubble auto-hides (0 = never hide) |
position |
string | "bottom-right" |
"bottom-right" or "bottom-left" |
bubbleColor |
string | "#2563eb" |
CSS color for the chat bubble |
title |
string | "Chat with us" |
Title shown in the chat header (room selector screen) |
placeholder |
string | - | Placeholder text for empty chat (overrides room's welcome message) |
tools |
array | [] |
Custom client-side tools (see below) |
containerId |
string | "soliplex-chat-widget" |
DOM element ID for the widget container |
Note: The
roomIdoption is still supported for backwards compatibility and will be converted toroomIds: [roomId].
<script src="https://your-domain.com/soliplex-chat.js"></script>
<script>
SoliplexChat.init({
baseUrl: "https://api.example.com",
roomIds: ["support", "sales"], // Only show these rooms
autoHideSeconds: 30,
position: "bottom-left",
bubbleColor: "#10b981",
title: "Need help?",
containerId: "my-chat-widget"
});
</script>The widget fetches available rooms from GET /api/v1/rooms when opened:
- No
roomIdsspecified: Shows all available rooms from the backend roomIdswith multiple IDs: Shows only those rooms, user picks oneroomIdswith single ID: Auto-selects that room, skips room selectionroomIdswith IDs not in backend: Those rooms are filtered out
Once a room is selected, the header shows the room's name and a back button (if multiple rooms are available) to return to room selection.
Initializes the widget with the given configuration. Can only be called once. Call destroy() first if you need to reinitialize.
Programmatically opens the chat panel.
document.getElementById('help-button').addEventListener('click', () => {
SoliplexChat.open();
});Programmatically closes the chat panel.
Completely removes the widget from the page. Useful for cleanup or reinitializing with different config.
// Change configuration
SoliplexChat.destroy();
SoliplexChat.init({ ...newConfig });Set autoHideSeconds to automatically hide the bubble after a period of inactivity:
SoliplexChat.init({
baseUrl: "https://my-server.example.com",
autoHideSeconds: 15 // Hide after 15 seconds if user hasn't interacted
});The bubble will reappear when the user moves their mouse near the corner where it was positioned.
Tools allow the AI agent to execute JavaScript functions in the user's browser. This is useful for:
- Getting information from the current page
- Interacting with your application's state
- Performing client-side actions
{
name: "tool_name", // Unique identifier (snake_case recommended)
description: "...", // What the tool does (helps the AI decide when to use it)
parameters: { // JSON Schema for the tool's arguments
type: "object",
properties: {
param1: { type: "string", description: "..." },
param2: { type: "number", description: "..." }
},
required: ["param1"] // Optional: list of required parameters
},
handler: "path.to.function" // String path OR inline function
}String Reference - Points to a function on the window object:
window.myApp = {
tools: {
getUser: async () => ({ name: "John", email: "john@example.com" })
}
};
// In config:
handler: "myApp.tools.getUser"Inline Function - Define the handler directly:
handler: async (args) => {
return { result: args.value * 2 };
}Get information about the current page:
<script src="soliplex-chat.js"></script>
<script>
window.pageTools = {
getPageInfo: async () => ({
title: document.title,
url: window.location.href,
referrer: document.referrer,
scrollPosition: window.scrollY,
viewportHeight: window.innerHeight,
documentHeight: document.documentElement.scrollHeight
})
};
SoliplexChat.init({
baseUrl: "https://my-server.example.com",
roomIds: ["support"],
tools: [
{
name: "get_page_info",
description: "Get information about the current page including URL, title, and scroll position",
parameters: { type: "object", properties: {} },
handler: "pageTools.getPageInfo"
}
]
});
</script>Tools for an e-commerce site:
<script src="soliplex-chat.js"></script>
<script>
window.shopTools = {
getCart: async () => {
// Your cart implementation
const cart = JSON.parse(localStorage.getItem('cart') || '[]');
return {
items: cart,
itemCount: cart.length,
total: cart.reduce((sum, item) => sum + item.price * item.quantity, 0)
};
},
addToCart: async ({ productId, quantity = 1 }) => {
const cart = JSON.parse(localStorage.getItem('cart') || '[]');
const existing = cart.find(item => item.productId === productId);
if (existing) {
existing.quantity += quantity;
} else {
// Fetch product details from your API
cart.push({ productId, quantity, price: 29.99, name: `Product ${productId}` });
}
localStorage.setItem('cart', JSON.stringify(cart));
return { success: true, cartSize: cart.length };
},
searchProducts: async ({ query, category }) => {
// Mock search - replace with your API
return {
results: [
{ id: "1", name: "Blue T-Shirt", price: 29.99, category: "clothing" },
{ id: "2", name: "Red Sneakers", price: 89.99, category: "shoes" }
].filter(p =>
p.name.toLowerCase().includes(query.toLowerCase()) &&
(!category || p.category === category)
)
};
}
};
SoliplexChat.init({
baseUrl: "https://my-server.example.com",
roomIds: ["shop-assistant"],
bubbleColor: "#f97316",
title: "Shopping Assistant",
tools: [
{
name: "get_cart",
description: "Get the current shopping cart contents and total",
parameters: { type: "object", properties: {} },
handler: "shopTools.getCart"
},
{
name: "add_to_cart",
description: "Add a product to the shopping cart",
parameters: {
type: "object",
properties: {
productId: {
type: "string",
description: "The product ID to add"
},
quantity: {
type: "number",
description: "Quantity to add (default: 1)"
}
},
required: ["productId"]
},
handler: "shopTools.addToCart"
},
{
name: "search_products",
description: "Search for products by name or category",
parameters: {
type: "object",
properties: {
query: {
type: "string",
description: "Search query"
},
category: {
type: "string",
description: "Optional category filter"
}
},
required: ["query"]
},
handler: "shopTools.searchProducts"
}
]
});
</script>Tools to help users fill out forms:
<script src="soliplex-chat.js"></script>
<script>
window.formTools = {
getFormFields: async () => {
const form = document.querySelector('form');
if (!form) return { error: "No form found on page" };
const fields = Array.from(form.elements)
.filter(el => el.name)
.map(el => ({
name: el.name,
type: el.type,
label: document.querySelector(`label[for="${el.id}"]`)?.textContent || el.name,
value: el.value,
required: el.required
}));
return { fields };
},
fillField: async ({ fieldName, value }) => {
const field = document.querySelector(`[name="${fieldName}"]`);
if (!field) return { error: `Field "${fieldName}" not found` };
field.value = value;
field.dispatchEvent(new Event('input', { bubbles: true }));
field.dispatchEvent(new Event('change', { bubbles: true }));
return { success: true, field: fieldName, newValue: value };
},
validateForm: async () => {
const form = document.querySelector('form');
if (!form) return { error: "No form found" };
const errors = [];
form.querySelectorAll('[required]').forEach(field => {
if (!field.value.trim()) {
errors.push({
field: field.name,
message: `${field.name} is required`
});
}
});
return {
valid: errors.length === 0,
errors
};
}
};
SoliplexChat.init({
baseUrl: "https://my-server.example.com",
roomIds: ["form-helper"],
title: "Form Assistant",
tools: [
{
name: "get_form_fields",
description: "Get all form fields on the current page with their labels and values",
parameters: { type: "object", properties: {} },
handler: "formTools.getFormFields"
},
{
name: "fill_field",
description: "Fill a form field with a value",
parameters: {
type: "object",
properties: {
fieldName: { type: "string", description: "The name attribute of the field" },
value: { type: "string", description: "The value to set" }
},
required: ["fieldName", "value"]
},
handler: "formTools.fillField"
},
{
name: "validate_form",
description: "Check if all required form fields are filled",
parameters: { type: "object", properties: {} },
handler: "formTools.validateForm"
}
]
});
</script>Tools that provide user context to the AI:
<script src="soliplex-chat.js"></script>
<script>
window.userTools = {
getUserInfo: async () => {
// Get from your auth system
const user = JSON.parse(localStorage.getItem('user') || 'null');
return user ? {
loggedIn: true,
name: user.name,
email: user.email,
memberSince: user.createdAt,
plan: user.subscription
} : {
loggedIn: false
};
},
getPreferences: async () => {
return {
theme: localStorage.getItem('theme') || 'light',
language: navigator.language,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
notifications: localStorage.getItem('notifications') === 'true'
};
},
getBrowserInfo: async () => ({
userAgent: navigator.userAgent,
platform: navigator.platform,
language: navigator.language,
cookiesEnabled: navigator.cookieEnabled,
screenSize: `${screen.width}x${screen.height}`,
windowSize: `${window.innerWidth}x${window.innerHeight}`
})
};
SoliplexChat.init({
baseUrl: "https://my-server.example.com",
roomIds: ["support"],
tools: [
{
name: "get_user_info",
description: "Get information about the currently logged in user",
parameters: { type: "object", properties: {} },
handler: "userTools.getUserInfo"
},
{
name: "get_preferences",
description: "Get the user's preferences and settings",
parameters: { type: "object", properties: {} },
handler: "userTools.getPreferences"
},
{
name: "get_browser_info",
description: "Get technical information about the user's browser for debugging",
parameters: { type: "object", properties: {} },
handler: "userTools.getBrowserInfo"
}
]
});
</script>Tools to help users navigate your site:
<script src="soliplex-chat.js"></script>
<script>
window.navTools = {
navigateTo: async ({ path }) => {
window.location.href = path;
return { navigating: true, destination: path };
},
scrollToSection: async ({ sectionId }) => {
const element = document.getElementById(sectionId);
if (!element) return { error: `Section "${sectionId}" not found` };
element.scrollIntoView({ behavior: 'smooth' });
return { success: true, scrolledTo: sectionId };
},
getSiteMap: async () => {
// Return your site structure
return {
pages: [
{ path: "/", name: "Home" },
{ path: "/products", name: "Products" },
{ path: "/about", name: "About Us" },
{ path: "/contact", name: "Contact" },
{ path: "/faq", name: "FAQ" }
]
};
},
highlightElement: async ({ selector }) => {
const element = document.querySelector(selector);
if (!element) return { error: "Element not found" };
const originalOutline = element.style.outline;
element.style.outline = "3px solid #2563eb";
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
setTimeout(() => {
element.style.outline = originalOutline;
}, 3000);
return { success: true, highlighted: selector };
}
};
SoliplexChat.init({
baseUrl: "https://my-server.example.com",
roomIds: ["navigator"],
title: "Site Guide",
tools: [
{
name: "navigate_to",
description: "Navigate to a different page on the site",
parameters: {
type: "object",
properties: {
path: { type: "string", description: "The URL path to navigate to" }
},
required: ["path"]
},
handler: "navTools.navigateTo"
},
{
name: "scroll_to_section",
description: "Scroll to a specific section on the current page",
parameters: {
type: "object",
properties: {
sectionId: { type: "string", description: "The ID of the section to scroll to" }
},
required: ["sectionId"]
},
handler: "navTools.scrollToSection"
},
{
name: "get_site_map",
description: "Get a list of all pages on the site",
parameters: { type: "object", properties: {} },
handler: "navTools.getSiteMap"
},
{
name: "highlight_element",
description: "Highlight an element on the page to show the user where something is",
parameters: {
type: "object",
properties: {
selector: { type: "string", description: "CSS selector for the element to highlight" }
},
required: ["selector"]
},
handler: "navTools.highlightElement"
}
]
});
</script>The widget includes a built-in get_current_time tool that returns the current time in the user's local timezone. This is automatically available without any configuration.
- Check browser console for errors
- Verify
baseUrlis correct and the backend is running (or omit it to let users enter the URL manually) - Ensure the script is loaded before calling
init()
- Check that the handler path is correct (e.g.,
"myApp.tools.myFunction") - Verify the function exists on the
windowobject beforeinit()is called - Check browser console for "Handler not found" errors
- Ensure your handler returns a Promise or is an async function
Ensure your backend allows requests from your frontend domain:
# FastAPI example
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000", "https://yourdomain.com"],
allow_methods=["*"],
allow_headers=["*"],
)