This guide shows you how to add Heyo to any JavaScript application, whether using vanilla JS, jQuery, or any library.
Add to your HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My App</title>
<script src="https://heyo.so/embed/script" defer data-project-id="YOUR_PROJECT_ID"></script>
</head>
<body>
<!-- Your app -->
</body>
</html>
Install via npm:
npm install @heyo.so/js
Then in your JavaScript:
// Use either import style
import HEYO from '@heyo.so/js'; // or: import { HEYO } from '@heyo.so/js'
// Initialize on page load
window.addEventListener('load', () => {
HEYO.init({ projectId: 'YOUR_PROJECT_ID' });
});
Load the script dynamically:
(function() {
const script = document.createElement('script');
script.src = 'https://heyo.so/embed/script';
script.defer = true;
script.setAttribute('data-project-id', 'YOUR_PROJECT_ID');
document.head.appendChild(script);
})();
// Show the chat widget
window.HEYO.show();
// Hide the chat widget
window.HEYO.hide();
// Toggle visibility
window.HEYO.toggle();
<button id="chat-button">Need Help?</button>
<script>
document.getElementById('chat-button').addEventListener('click', () => {
window.HEYO?.show();
});
</script>
window.addEventListener('load', () => {
if (window.HEYO) {
// Widget is ready
console.log('Heyo is loaded');
}
});
window.addEventListener('load', () => {
const user = getUserFromSession(); // Your auth logic
if (user) {
window.HEYO.init({
projectId: 'YOUR_PROJECT_ID',
user: {
name: user.name,
email: user.email,
id: user.id
}
});
}
});
Track when chat opens/closes:
window.HEYO.onOpen(() => {
console.log('Chat was opened');
analytics.track('chat_opened');
});
window.HEYO.onClose(() => {
console.log('Chat was closed');
analytics.track('chat_closed');
});
Track widget ready state:
window.HEYO.onReady(() => {
console.log('Heyo widget is fully loaded');
});
Track agent status changes:
window.HEYO.onAgentStatusChange((status) => {
console.log('Agent status:', status); // 'online', 'away', or 'offline'
if (status === 'online') {
showNotification('Support is available!');
}
});
For SPAs that change routes without page reload:
// Call on route change
function onRouteChange(route) {
// Show/hide chat based on route
if (route === '/checkout') {
window.HEYO?.hide();
} else {
window.HEYO?.show();
}
}
// Your router integration
router.on('routeChange', onRouteChange);
$(document).ready(function() {
// Initialize Heyo
if (window.HEYO) {
window.HEYO.init({ projectId: 'YOUR_PROJECT_ID' });
}
// Custom button
$('#chat-trigger').on('click', function(e) {
e.preventDefault();
window.HEYO?.show();
});
});
async function initializeChat() {
// Wait for user data
const user = await fetchUserData();
// Initialize with user context
window.HEYO?.init({
projectId: 'YOUR_PROJECT_ID',
user: {
name: user.name,
email: user.email
}
});
}
window.addEventListener('load', initializeChat);
const Chat = (function() {
let initialized = false;
function init(projectId, userData) {
if (initialized) return;
window.HEYO?.init({
projectId,
user: userData
});
initialized = true;
}
function open() {
window.HEYO?.show();
}
function close() {
window.HEYO?.hide();
}
return {
init,
open,
close
};
})();
// Usage
Chat.init('YOUR_PROJECT_ID', { name: 'John', email: '[email protected]' });
Chat.open();
class HeyoChat {
constructor(projectId) {
this.projectId = projectId;
this.init();
}
init() {
window.addEventListener('load', () => {
window.HEYO?.init({ projectId: this.projectId });
});
}
show() {
window.HEYO?.show();
}
hide() {
window.HEYO?.hide();
}
setUser(user) {
window.HEYO?.init({
projectId: this.projectId,
user
});
}
}
// Usage
const chat = new HeyoChat('YOUR_PROJECT_ID');
chat.show();
Add type definitions:
interface DynamicProjectSettings {
widgetColor?: string;
widgetStyle?: 'bubble' | 'agent-card';
widgetPosition?: 'left' | 'right';
widgetSize?: 'small' | 'medium' | 'large';
}
declare global {
interface Window {
HEYO: {
_ready: boolean;
show: (options?: { force?: boolean }) => void;
hide: () => void;
open: (options?: { force?: boolean }) => void;
close: () => void;
toggle: () => void;
logout: () => void;
isOpen: () => boolean;
identify: (meta: Record<string, unknown>) => void;
configure: (settings: Partial<DynamicProjectSettings>) => void;
getAgentStatus: () => 'online' | 'away' | 'offline';
onAgentStatusChange: (callback: (status: 'online' | 'away' | 'offline') => void) => void;
onReady: (callback: () => void) => void;
onOpen: (callback: () => void) => void;
onClose: (callback: () => void) => void;
addTag: (tag: string) => void;
removeTag: (tag: string) => void;
setTags: (tags: string[]) => void;
setField: (key: string, value: string | number | boolean) => void;
removeField: (key: string) => void;
};
}
}
export {};
Usage in TypeScript:
class ChatWidget {
constructor() {
this.setupEventListeners();
}
private setupEventListeners(): void {
window.HEYO?.onReady(() => {
console.log('Chat widget ready');
});
window.HEYO?.onOpen(() => {
console.log('Chat opened');
});
window.HEYO?.onClose(() => {
console.log('Chat closed');
});
window.HEYO?.onAgentStatusChange((status) => {
this.handleStatusChange(status);
});
}
private handleStatusChange(status: 'online' | 'away' | 'offline'): void {
console.log('Agent status:', status);
}
public show(): void {
window.HEYO?.show();
}
public hide(): void {
window.HEYO?.hide();
}
public open(): void {
window.HEYO?.open();
}
public close(): void {
window.HEYO?.close();
}
}
defer attribute)load event before calling HEYO methods?.) when calling HEYO methodswindow.addEventListener('load', ...)init() once per page