Skip to Content
Chat WidgetEvents System

Events System

The Nexus Chat Widget emits events for all user interactions and widget lifecycle changes. Use these events to build analytics, custom UI, integrations, and advanced features.

Available Events

The widget supports 19+ event types covering UI lifecycle, sessions, messages, interactions, voice/TTS, and errors.

UI Lifecycle Events

EventDescriptionData
openWidget opened by user{ sessionId, timestamp }
closeWidget closed by user{ sessionId, timestamp }
minimizeWidget minimized{ previousMode, sessionId }
maximizeWidget maximized{ previousMode, sessionId }

Session Events

EventDescriptionData
sessionStartNew chat session created{ sessionId, metadata }
sessionEndChat session ended{ sessionId, duration, messageCount }
sessionClearUser explicitly cleared chat{ sessionId?, messageCount, timestamp }

Message Events

EventDescriptionData
messageStartUser submitted a message{ message, timestamp }
messageCompleteAI response completed{ answer, queryId, duration }
messageChunkStreaming message chunk received{ chunk, queryId }

Interaction Events

EventDescriptionData
typingUser is typing{ text, length }
typingStopUser stopped typing{ finalText }
feedbackUser submitted feedback{ rating, messageId, comment? }
copyUser copied message content{ content, messageId }

Voice & TTS Events

EventDescriptionData
voiceStartVoice recognition started{ language, sessionId }
voiceEndVoice recognition ended{ transcript, duration }
ttsStartText-to-speech started{ text, messageId }
ttsEndText-to-speech ended{ duration, messageId }

Error Events

EventDescriptionData
errorError occurred{ type, message, stack?, details? }

Listening to Events

Use the widget.on() method to register event listeners:

// Initialize widget
const widget = window.NexusChatWidget.init({
  experienceId: "your-experience-id",
  apiUrl: "https://nexus-api.uat.knowbl.com",
});

// Listen to specific event
widget.on("messageComplete", (data) => {
console.log("AI responded:", data.answer);
console.log("Response time:", data.duration, "ms");
});

Complete Example

Here’s a comprehensive example that listens to all event types:

const widget = window.NexusChatWidget.init({
  experienceId: "your-experience-id",
  apiUrl: "https://nexus-api.uat.knowbl.com",
});

// UI Lifecycle Events
widget.on("open", (data) => {
console.log("Widget opened", data.sessionId);
});

widget.on("close", (data) => {
console.log("Widget closed", data.sessionId);
});

widget.on("minimize", (data) => {
console.log("Widget minimized from", data.previousMode);
});

widget.on("maximize", (data) => {
console.log("Widget maximized from", data.previousMode);
});

// Session Events
widget.on("sessionStart", (data) => {
console.log("Session started:", data.sessionId);
});

widget.on("sessionClear", (data) => {
console.log("Session cleared:", {
sessionId: data.sessionId,
messageCount: data.messageCount,
});
});

widget.on("sessionEnd", (data) => {
console.log("Session ended:", {
sessionId: data.sessionId,
duration: data.duration,
messageCount: data.messageCount,
});
});

// Message Events
widget.on("messageStart", (data) => {
console.log("User message:", data.message);
});

widget.on("messageComplete", (data) => {
console.log("AI response:", {
answer: data.answer,
queryId: data.queryId,
duration: data.duration,
});
});

// Interaction Events
widget.on("typing", (data) => {
console.log("User typing...", data.length, "characters");
});

widget.on("typingStop", () => {
console.log("User stopped typing");
});

widget.on("feedback", (data) => {
console.log("User feedback:", data.rating, "for message", data.messageId);
if (data.comment) {
console.log("Comment:", data.comment);
}
});

widget.on("copy", (data) => {
console.log("User copied message:", data.messageId);
});

// Voice Events
widget.on("voiceStart", (data) => {
console.log("Voice input started, language:", data.language);
});

widget.on("voiceEnd", (data) => {
console.log("Voice input ended:", {
transcript: data.transcript,
duration: data.duration,
});
});

// TTS Events
widget.on("ttsStart", (data) => {
console.log("TTS started for message:", data.messageId);
});

widget.on("ttsEnd", (data) => {
console.log("TTS ended, duration:", data.duration);
});

// Error Handling
widget.on("error", (error) => {
console.error("Widget error:", {
type: error.type,
message: error.message,
details: error.details,
});
});

Analytics Integration

Google Analytics

Track key metrics with Google Analytics:

widget.on("sessionStart", (data) => {
  gtag("event", "chat_session_start", {
    session_id: data.sessionId,
  });
});

widget.on("messageComplete", (data) => {
gtag("event", "chat_message_complete", {
session_id: data.sessionId,
response_time: data.duration,
answer_length: data.answer.length,
});
});

widget.on("feedback", (data) => {
gtag("event", "chat_feedback", {
session_id: data.sessionId,
rating: data.rating,
message_id: data.messageId,
});
});

widget.on("error", (error) => {
gtag("event", "chat_error", {
error_type: error.type,
error_message: error.message,
});
});

Mixpanel

Track events with Mixpanel:

widget.on("sessionStart", (data) => {
  mixpanel.track("Chat Session Started", {
    session_id: data.sessionId,
    timestamp: data.timestamp,
  });
});

widget.on("messageComplete", (data) => {
mixpanel.track("Chat Message Completed", {
session_id: data.sessionId,
response_time: data.duration,
query_id: data.queryId,
});
});

widget.on("feedback", (data) => {
mixpanel.track("Chat Feedback", {
rating: data.rating,
message_id: data.messageId,
has_comment: !!data.comment,
});
});

Segment

Send events to Segment:

widget.on("sessionStart", (data) => {
  analytics.track("Chat Session Started", {
    sessionId: data.sessionId,
  });
});

widget.on("messageComplete", (data) => {
analytics.track("Chat Message Completed", {
sessionId: data.sessionId,
responseTime: data.duration,
queryId: data.queryId,
});
});

Use Cases

Custom UI Updates

Update your UI based on widget state:

const statusIndicator = document.getElementById("chat-status");

widget.on("open", () => {
statusIndicator.textContent = "Chat Open";
statusIndicator.className = "status-active";
});

widget.on("close", () => {
statusIndicator.textContent = "Chat Closed";
statusIndicator.className = "status-inactive";
});

widget.on("messageStart", () => {
statusIndicator.textContent = "Processing...";
});

widget.on("messageComplete", () => {
statusIndicator.textContent = "Ready";
});

Session Recording

Record chat sessions for playback:

const sessionData = {
  events: [],
  startTime: null,
  endTime: null,
};

widget.on("sessionStart", (data) => {
sessionData.startTime = data.timestamp;
sessionData.events = [];
});

widget.on("messageStart", (data) => {
sessionData.events.push({
type: "userMessage",
content: data.message,
timestamp: data.timestamp,
});
});

widget.on("messageComplete", (data) => {
sessionData.events.push({
type: "assistantMessage",
content: data.answer,
timestamp: new Date(),
duration: data.duration,
});
});

widget.on("sessionEnd", (data) => {
sessionData.endTime = data.timestamp;
// Send to your backend for storage
fetch("/api/chat-sessions", {
method: "POST",
body: JSON.stringify(sessionData),
});
});

Performance Monitoring

Track widget performance metrics:

const metrics = {
  totalMessages: 0,
  totalResponseTime: 0,
  errors: 0,
};

widget.on("messageComplete", (data) => {
metrics.totalMessages++;
metrics.totalResponseTime += data.duration;

const avgResponseTime = metrics.totalResponseTime / metrics.totalMessages;
console.log("Average response time:", avgResponseTime, "ms");
});

widget.on("error", () => {
metrics.errors++;
console.log(
"Error rate:",
(metrics.errors / metrics.totalMessages) * 100,
"%",
);
});

Tracking Session Clears

Track when users explicitly clear conversations:

// Track when users explicitly clear conversations
widget.on("sessionClear", (data) => {
  // Log to analytics
  analytics.track("Chat Cleared", {
    sessionId: data.sessionId,
    messageCount: data.messageCount,
    timestamp: data.timestamp,
  });

// Optional: Show confirmation message
console.log(`Cleared ${data.messageCount} messages`);

// Optional: Save conversation before clearing
if (data.messageCount > 0) {
fetch("/api/save-conversation", {
method: "POST",
body: JSON.stringify({
sessionId: data.sessionId,
clearedAt: data.timestamp,
}),
});
}
});

Use Cases:

  • Analytics: Track how often users clear conversations
  • Data retention: Save conversation history before clearing
  • User feedback: Prompt for feedback when clearing after many messages
  • Session recovery: Allow users to undo clear action within a time window

Error Tracking with Sentry

Send errors to Sentry:

widget.on("error", (error) => {
  Sentry.captureException(new Error(error.message), {
    tags: {
      component: "chat-widget",
      errorType: error.type,
    },
    extra: {
      sessionId: error.sessionId,
      details: error.details,
      stack: error.stack,
    },
  });
});

Event Data Reference

Common Fields

All events include:

  • timestamp - ISO 8601 format timestamp
  • sessionId - Current session identifier (when applicable)

Duration Fields

Duration measurements in milliseconds for:

  • sessionEnd.duration - Session length
  • messageComplete.duration - Response time
  • voiceEnd.duration - Voice input duration
  • ttsEnd.duration - TTS playback duration

Error Types

The error event includes a type field:

  • interceptor - Message interceptor error
  • timeout - Request timeout
  • backend - Backend API error
  • feedback - Feedback submission error
  • unknown - Unclassified error

Interactive Demo

See the Events System Demo to watch events fire in real-time as you interact with the widget.

Next Steps