Skip to main content

Vanilla JavaScript Integration

Integrate Ozwell into any website using plain JavaScript, without any framework dependencies.

Current Demo Environment

Production CDN examples such as cdn.ozwell.ai are future production examples. For now, use the dev-container loader at https://ozwellapi.os.mieweb.org/embed/ozwell-loader.js.

Quick Start​

Script Tag (CDN)​

The simplest approach β€” add a single script tag:

<script 
src="https://cdn.ozwell.ai/embed.js"
data-api-key="ozw_scoped_xxxxxxxx"
data-agent-id="agent_xxxxxxxx"
></script>

See the CDN documentation for full details.

ES Module Import​

For bundled applications:

import { Ozwell } from '@ozwell/vanilla';

const ozwell = new Ozwell({
apiKey: 'ozw_scoped_xxxxxxxx',
agentId: 'agent_xxxxxxxx',
});

ozwell.mount('#ozwell-container');

Installation​

NPM / Yarn / PNPM​

npm install @ozwell/vanilla
# or
yarn add @ozwell/vanilla
# or
pnpm add @ozwell/vanilla

CDN (IIFE)​

<script src="https://cdn.ozwell.ai/ozwell.min.js"></script>
<script>
const ozwell = new Ozwell.default({
apiKey: 'ozw_scoped_xxxxxxxx',
agentId: 'agent_xxxxxxxx',
});
ozwell.mount(document.body);
</script>

API Reference​

Constructor​

import { Ozwell } from '@ozwell/vanilla';

const ozwell = new Ozwell({
// Required
apiKey: 'ozw_scoped_xxxxxxxx',
agentId: 'agent_xxxxxxxx',

// Optional
theme: 'auto', // 'light' | 'dark' | 'auto'
position: 'bottom-right', // 'bottom-right' | 'bottom-left'
primaryColor: '#4f46e5',
width: '400px',
height: '600px',
autoOpen: false,
greeting: 'Hello! How can I help?',
placeholder: 'Type a message...',
showTrigger: true,
context: {},
});

Configuration Options​

OptionTypeDefaultDescription
apiKeystringrequiredScoped API key
agentIdstringrequiredAgent ID
themestring'auto'Color theme
positionstring'bottom-right'Widget position
primaryColorstring'#4f46e5'Accent color
widthstring'400px'Chat window width
heightstring'600px'Chat window height
autoOpenbooleanfalseOpen on mount
greetingstringAgent defaultInitial message
placeholderstring'Type a message...'Input placeholder
showTriggerbooleantrueShow launcher button
contextobject{}Context data for agent

Methods​

mount(target)​

Mount the widget to a DOM element.

// Using a selector
ozwell.mount('#container');

// Using an element reference
ozwell.mount(document.body);

unmount()​

Remove the widget from the DOM.

ozwell.unmount();

open()​

Open the chat window.

ozwell.open();

close()​

Close the chat window.

ozwell.close();

toggle()​

Toggle the chat window open/closed.

ozwell.toggle();

sendMessage(content)​

Send a message programmatically.

ozwell.sendMessage('Hello, I need help with...');

setContext(context)​

Update the context data sent to the agent.

ozwell.setContext({
userId: 'user_123',
page: window.location.pathname,
customData: { ... },
});

updateConfig(options)​

Update widget configuration.

ozwell.updateConfig({
theme: 'dark',
primaryColor: '#10b981',
});

Properties​

PropertyTypeDescription
isReadybooleanWidget is initialized
isOpenbooleanChat window is open
isMountedbooleanWidget is mounted to DOM
if (ozwell.isReady && !ozwell.isOpen) {
ozwell.open();
}

Events​

Listen to widget events:

ozwell.on('ready', () => {
console.log('Widget ready');
});

ozwell.on('open', () => {
console.log('Chat opened');
});

ozwell.on('close', () => {
console.log('Chat closed');
});

ozwell.on('user-share', (data) => {
// Only fires when user explicitly shares
console.log('User shared:', data);
});

ozwell.on('error', (error) => {
console.error('Error:', error);
});

// Note: No 'message' event - conversations are private between user and Ozwell

off(event, handler)​

Remove an event listener:

function handleOpen() {
console.log('Opened');
}

ozwell.on('open', handleOpen);
ozwell.off('open', handleOpen);

Examples​

Basic Setup​

<!DOCTYPE html>
<html>
<head>
<title>My Website</title>
</head>
<body>
<h1>Welcome</h1>

<div id="ozwell-container"></div>

<script type="module">
import { Ozwell } from 'https://cdn.ozwell.ai/ozwell.esm.js';

const ozwell = new Ozwell({
apiKey: 'ozw_scoped_xxxxxxxx',
agentId: 'agent_xxxxxxxx',
});

ozwell.mount('#ozwell-container');
</script>
</body>
</html>

Custom Trigger Button​

<button id="chat-button">πŸ’¬ Chat with us</button>

<div id="ozwell-container"></div>

<script type="module">
import { Ozwell } from '@ozwell/vanilla';

const ozwell = new Ozwell({
apiKey: 'ozw_scoped_xxxxxxxx',
agentId: 'agent_xxxxxxxx',
showTrigger: false,
});

ozwell.mount('#ozwell-container');

document.getElementById('chat-button').addEventListener('click', () => {
ozwell.toggle();
});
</script>

With User Context​

import { Ozwell } from '@ozwell/vanilla';

// Get user data from your application
const user = getCurrentUser();

const ozwell = new Ozwell({
apiKey: 'ozw_scoped_xxxxxxxx',
agentId: 'agent_xxxxxxxx',
context: {
userId: user?.id,
email: user?.email,
plan: user?.subscription?.plan,
page: window.location.pathname,
},
});

ozwell.mount(document.body);

// Update context when user navigates
window.addEventListener('popstate', () => {
ozwell.setContext({
...ozwell.context,
page: window.location.pathname,
});
});

Analytics Integration​

Track chat lifecycle events (not contentβ€”that's private):

import { Ozwell } from '@ozwell/vanilla';
import { track } from './analytics';

const ozwell = new Ozwell({
apiKey: 'ozw_scoped_xxxxxxxx',
agentId: 'agent_xxxxxxxx',
});

ozwell.on('open', () => {
track('chat_opened');
});

ozwell.on('close', () => {
track('chat_closed');
});

ozwell.on('user-share', (data) => {
// Only fires when user explicitly shares
track('user_shared_data', data);
});

ozwell.mount(document.body);

Conditional Display​

import { Ozwell } from '@ozwell/vanilla';

const ozwell = new Ozwell({
apiKey: 'ozw_scoped_xxxxxxxx',
agentId: 'agent_xxxxxxxx',
});

// Only show on certain pages
const hiddenPaths = ['/checkout', '/auth', '/admin'];

function shouldShowChat() {
return !hiddenPaths.some(path =>
window.location.pathname.startsWith(path)
);
}

if (shouldShowChat()) {
ozwell.mount(document.body);
}

// Handle SPA navigation
window.addEventListener('popstate', () => {
if (shouldShowChat() && !ozwell.isMounted) {
ozwell.mount(document.body);
} else if (!shouldShowChat() && ozwell.isMounted) {
ozwell.unmount();
}
});

Multiple Agents (Route-Based)​

import { Ozwell } from '@ozwell/vanilla';

const agents = {
'/docs': 'agent_docs_xxxxxxxx',
'/support': 'agent_support_xxxxxxxx',
default: 'agent_general_xxxxxxxx',
};

function getAgentForPath(path) {
for (const [prefix, agentId] of Object.entries(agents)) {
if (prefix !== 'default' && path.startsWith(prefix)) {
return agentId;
}
}
return agents.default;
}

let ozwell = new Ozwell({
apiKey: 'ozw_scoped_xxxxxxxx',
agentId: getAgentForPath(window.location.pathname),
});

ozwell.mount(document.body);

// Reinitialize on navigation
window.addEventListener('popstate', () => {
const newAgentId = getAgentForPath(window.location.pathname);

if (ozwell.config.agentId !== newAgentId) {
ozwell.unmount();
ozwell = new Ozwell({
apiKey: 'ozw_scoped_xxxxxxxx',
agentId: newAgentId,
});
ozwell.mount(document.body);
}
});

TypeScript​

Full TypeScript definitions are included:

import { Ozwell, type OzwellConfig, type Message, type OzwellError } from '@ozwell/vanilla';

const config: OzwellConfig = {
apiKey: 'ozw_scoped_xxxxxxxx',
agentId: 'agent_xxxxxxxx',
theme: 'dark',
};

const ozwell = new Ozwell(config);

ozwell.on('message', (message: Message) => {
console.log(message.role, message.content);
});

ozwell.on('error', (error: OzwellError) => {
console.error(error.code, error.message);
});

ozwell.mount(document.body);

Troubleshooting​

Widget Not Appearing​

  1. Check that the container element exists in the DOM
  2. Verify mount() is called after DOM is ready
  3. Check browser console for errors

Events Not Firing​

  1. Register event listeners before calling mount()
  2. Verify the event names are correct

Multiple Instances​

Only create one Ozwell instance per page. If you need different agents, use unmount() and create a new instance.


Next Steps​