Event Handling
Learn how to listen to and handle events from the Chatoshi SDK for building interactive crypto assistant experiences.
Event Handling
The Chatoshi SDK uses an event-driven architecture that allows you to listen to various chat events and respond accordingly. This enables you to create dynamic, interactive experiences that react to user interactions with the crypto assistant.
Event System Overview
The SDK emits events for:
- Application lifecycle (ready, error states)
- User interactions (popup/drawer open/close)
- Chat communication (messages sent and received)
Basic Event Handling
Adding Event Listeners
Use the on() method to listen for events:
import Chatoshi from 'chatoshi-sdk';
const chat = new Chatoshi({
partnerKey: 'your-partner-key',
mode: 'popup'
});
// Listen for when chat is ready
chat.on('app:ready', () => {
console.log('Chatoshi crypto assistant is ready!');
});
// Listen for popup events
chat.on('popup:open', () => {
console.log('User opened the crypto assistant');
});
chat.on('popup:close', () => {
console.log('User closed the crypto assistant');
});
Removing Event Listeners
Use the off() method to remove listeners:
// Remove specific listener
const handler = () => console.log('Crypto assistant opened');
chat.on('popup:open', handler);
chat.off('popup:open', handler);
// Remove all listeners for an event
chat.off('popup:open');
// Method chaining is supported
chat.on('app:ready', readyHandler)
.on('popup:open', openHandler)
.off('popup:close'); // Remove all close listeners
Core Events
Application Events
app:ready
Fired when the crypto assistant application is fully loaded and ready.
chat.on('app:ready', () => {
console.log('Chatoshi is ready!');
// Safe to call other methods now
document.getElementById('crypto-status').textContent = 'Online';
});
app:error
Fired when there's an application error.
chat.on('app:error', (error) => {
console.error('Crypto assistant error:', error);
// Show fallback UI
document.getElementById('chat-fallback').style.display = 'block';
});
Communication Events
message:sent
Fired when a user sends a message to the crypto assistant.
chat.on('message:sent', (data) => {
console.log('User asked:', data.message);
console.log('Timestamp:', data.timestamp);
// Track user engagement
analytics.track('crypto_query', {
message_length: data.message.length,
timestamp: data.timestamp
});
});
message:received
Fired when the crypto assistant responds to the user.
chat.on('message:received', (data) => {
console.log('AI response:', data.message);
console.log('Response time:', data.responseTime);
// Track response quality or speed
analytics.track('ai_response', {
response_time: data.responseTime,
message_type: data.type
});
});
UI Events
Popup Events
// Popup opened
chat.on('popup:open', () => {
// Track analytics
gtag('event', 'crypto_assistant_opened', {
'event_category': 'engagement',
'event_label': 'popup'
});
// Pause background videos
document.querySelectorAll('video').forEach(video => video.pause());
});
// Popup closed
chat.on('popup:close', () => {
// Track analytics
gtag('event', 'crypto_assistant_closed', {
'event_category': 'engagement',
'event_label': 'popup'
});
// Resume background videos
document.querySelectorAll('video').forEach(video => video.play());
});
Drawer Events
// Drawer opened
chat.on('drawer:open', () => {
console.log('Crypto assistant drawer opened');
// Add blur effect to main content
document.querySelector('.main-content').classList.add('blurred');
});
// Drawer closed
chat.on('drawer:close', () => {
console.log('Crypto assistant drawer closed');
// Remove blur effect
document.querySelector('.main-content').classList.remove('blurred');
## Practical Examples
### Complete Event Setup
Here's a complete example showing all available events:
```javascript
const chat = new Chatoshi({
partnerKey: 'your-partner-key',
mode: 'popup'
});
// Application lifecycle events
chat.on('app:ready', () => {
console.log('Chatoshi crypto assistant is ready!');
document.getElementById('chat-status').textContent = 'Online';
});
chat.on('app:error', (error) => {
console.error('Application error:', error);
document.getElementById('chat-status').textContent = 'Offline';
});
// Communication events
chat.on('message:sent', (data) => {
console.log('User question:', data.message);
// Track user engagement with crypto queries
analytics.track('crypto_query_sent', {
query_length: data.message.length
});
});
chat.on('message:received', (data) => {
console.log('AI response received:', data.message);
// Track response quality metrics
analytics.track('ai_response_received', {
response_type: data.type || 'general'
});
});
// UI interaction events
chat.on('popup:open', () => {
console.log('Crypto assistant opened');
// Pause background content
document.querySelectorAll('video').forEach(v => v.pause());
});
chat.on('popup:close', () => {
console.log('Crypto assistant closed');
// Resume background content
document.querySelectorAll('video').forEach(v => v.play());
});
chat.on('drawer:open', () => {
console.log('Crypto assistant drawer opened');
document.body.classList.add('drawer-open');
});
chat.on('drawer:close', () => {
console.log('Crypto assistant drawer closed');
document.body.classList.remove('drawer-open');
});
Event-Driven Analytics
Track user interactions for insights:
class CryptoAssistantAnalytics {
constructor(chat) {
this.chat = chat;
this.sessionStart = null;
this.messageCount = 0;
this.setupTracking();
}
setupTracking() {
// Track session start
this.chat.on('popup:open', () => {
if (!this.sessionStart) {
this.sessionStart = Date.now();
}
});
// Track user engagement
this.chat.on('message:sent', () => {
this.messageCount++;
});
// Track session end
this.chat.on('popup:close', () => {
if (this.sessionStart) {
const sessionDuration = Date.now() - this.sessionStart;
// Send analytics
gtag('event', 'crypto_assistant_session', {
'session_duration': sessionDuration,
'messages_sent': this.messageCount,
'event_category': 'crypto_engagement'
});
// Reset for next session
this.sessionStart = null;
this.messageCount = 0;
}
});
}
}
// Initialize analytics
const analytics = new CryptoAssistantAnalytics(chat);
Conditional UI Updates
Update your interface based on assistant state:
// Update status indicator
chat.on('app:ready', () => {
const indicator = document.querySelector('.crypto-assistant-status');
if (indicator) {
indicator.className = 'crypto-assistant-status online';
indicator.textContent = 'AI Crypto Assistant Online';
}
});
chat.on('app:error', () => {
const indicator = document.querySelector('.crypto-assistant-status');
if (indicator) {
indicator.className = 'crypto-assistant-status offline';
indicator.textContent = 'Assistant Temporarily Unavailable';
}
});
// Show notification badge for new responses when popup is closed
chat.on('message:received', () => {
const popup = chat.getPopup();
if (popup && !popup.isOpen()) {
document.querySelector('.chat-notification-badge')?.classList.add('visible');
}
});
// Clear notification badge when popup opens
chat.on('popup:open', () => {
document.querySelector('.chat-notification-badge')?.classList.remove('visible');
});
Error Handling
Handle errors gracefully:
chat.on('app:error', (error) => {
console.error('Crypto assistant error:', error);
// Show user-friendly message
showToast('Crypto assistant is temporarily unavailable. Please try again in a moment.', 'error');
// Log for debugging
if (window.logError) {
window.logError('chatoshi_error', {
message: error.message,
timestamp: new Date().toISOString()
});
}
});
function showToast(message, type = 'info') {
const toast = document.createElement('div');
toast.className = `toast toast-${type}`;
toast.textContent = message;
document.body.appendChild(toast);
setTimeout(() => toast.remove(), 5000);
}
Event Cleanup
Always clean up event listeners to prevent memory leaks:
class CryptoAssistantManager {
constructor() {
this.chat = null;
this.eventHandlers = new Map();
}
initialize() {
this.chat = new Chatoshi({
partnerKey: 'your-partner-key',
mode: 'popup'
});
// Store handlers for cleanup
this.eventHandlers.set('app:ready', () => this.onReady());
this.eventHandlers.set('app:error', (error) => this.onError(error));
this.eventHandlers.set('popup:open', () => this.onOpen());
this.eventHandlers.set('popup:close', () => this.onClose());
// Add listeners
this.eventHandlers.forEach((handler, event) => {
this.chat.on(event, handler);
});
}
destroy() {
if (this.chat) {
// Remove all event listeners
this.eventHandlers.forEach((handler, event) => {
this.chat.off(event, handler);
});
// Destroy chat instance
this.chat.destroy();
this.chat = null;
}
}
onReady() {
console.log('Crypto assistant ready');
}
onError(error) {
console.error('Error:', error);
}
onOpen() {
console.log('Assistant opened');
}
onClose() {
console.log('Assistant closed');
}
}
// Usage
const manager = new CryptoAssistantManager();
manager.initialize();
// Clean up when page unloads
window.addEventListener('beforeunload', () => {
manager.destroy();
});