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 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();
});