Overview
The AI Chat Extension SDK provides a comprehensive event system that notifies your extension about user interactions, query classifications, and UI state changes. Events enable you to track user behavior, trigger analytics, and respond to chat interactions.
Registering event listeners
Use the registerEventListener method to subscribe to SDK events:
import {
getAiChatExtensionSdk,
AiChatExtensionSdkEventType,
} from '@sleek/ai-chat-extension-sdk';
getAiChatExtensionSdk().registerEventListener((event, context) => {
console.log('Event type:', event.type);
console.log('Event data:', event.data);
console.log('Tab context:', context);
switch (event.type) {
case AiChatExtensionSdkEventType.QUERY_CLASSIFIED:
// Handle query classification
break;
case AiChatExtensionSdkEventType.CHAT_PANEL_OPENED:
// Handle panel opened
break;
// ... handle other events
}
});
You can register multiple listeners, and all will be called when an event occurs.
Event structure
All events follow this structure:
interface AiChatExtensionSdkEvent {
type: AiChatExtensionSdkEventType;
data: any; // Type varies by event
}
interface EventContext {
tabId: number;
url: string;
}
- type: The event type (see available events below)
- data: Event-specific payload
- context: Information about the tab where the event occurred
Available events
QUERY_CLASSIFIED
Emitted when a user’s query has been analyzed and classified.
Event type: AiChatExtensionSdkEventType.QUERY_CLASSIFIED
Data payload:
{
classification: 'shopping' | 'unknown';
query: string;
suggestedPrompts: string[];
}
Example:
case AiChatExtensionSdkEventType.QUERY_CLASSIFIED:
if (event.data.classification === 'shopping') {
console.log(`Shopping query detected: "${event.data.query}"`);
console.log('Suggested prompts:', event.data.suggestedPrompts);
// Track in analytics
analytics.track('shopping_query_detected', {
query: event.data.query,
promptCount: event.data.suggestedPrompts.length,
});
}
break;
When it fires:
- User enters a search query on Google Search
- User sends a message on ChatGPT
- Page loads with an existing query
CHAT_BADGE_SHOWN
Emitted when the chat badge becomes visible to the user (after a shopping query is classified).
Event type: AiChatExtensionSdkEventType.CHAT_BADGE_SHOWN
Data payload:
{
query: string;
suggestedPrompts: string[];
}
Example:
case AiChatExtensionSdkEventType.CHAT_BADGE_SHOWN:
console.log('Badge shown for query:', event.data.query);
// Track badge impressions
analytics.track('chat_badge_impression', {
query: event.data.query,
url: context.url,
});
break;
When it fires:
- Immediately after a query is classified as “shopping” (if badge is enabled)
CHAT_BADGE_CLICKED
Emitted when a user clicks on the chat badge or one of its suggested prompts.
Event type: AiChatExtensionSdkEventType.CHAT_BADGE_CLICKED
Data payload:
{
prompt?: string; // The specific prompt clicked, or undefined if badge itself clicked
}
Example:
case AiChatExtensionSdkEventType.CHAT_BADGE_CLICKED:
if (event.data.prompt) {
console.log('User clicked suggested prompt:', event.data.prompt);
// Track specific prompt clicks
analytics.track('suggested_prompt_clicked', {
prompt: event.data.prompt,
});
} else {
console.log('User clicked badge to open chat');
// Track badge clicks
analytics.track('chat_badge_clicked');
}
break;
When it fires:
- User clicks the chat badge itself
- User clicks one of the suggested prompts
This event fires immediately before CHAT_PANEL_OPENED if the panel feature is enabled.
CHAT_BADGE_CLOSED
Emitted when a user dismisses the chat badge without interacting with it.
Event type: AiChatExtensionSdkEventType.CHAT_BADGE_CLOSED
Data payload:
{
suggestedPrompts: string[];
}
Example:
case AiChatExtensionSdkEventType.CHAT_BADGE_CLOSED:
console.log('User dismissed badge');
// Track dismissals to understand friction
analytics.track('chat_badge_dismissed', {
promptCount: event.data.suggestedPrompts.length,
});
break;
When it fires:
- User clicks the close/dismiss button on the badge
CHAT_PANEL_OPENED
Emitted when the chat panel becomes visible to the user.
Event type: AiChatExtensionSdkEventType.CHAT_PANEL_OPENED
Data payload:
{
initialMessage?: string; // The prompt or message that opened the panel
}
Example:
case AiChatExtensionSdkEventType.CHAT_PANEL_OPENED:
console.log('Chat panel opened');
if (event.data.initialMessage) {
console.log('With initial message:', event.data.initialMessage);
}
// Track panel opens
analytics.track('chat_panel_opened', {
hasInitialMessage: !!event.data.initialMessage,
source: event.data.initialMessage ? 'badge_prompt' : 'badge_click',
});
// Start session timer
sessionTimers.set(context.tabId, Date.now());
break;
When it fires:
- User clicks the chat badge
- User clicks a suggested prompt on the badge
CHAT_PANEL_CLOSED
Emitted when the user closes the chat panel.
Event type: AiChatExtensionSdkEventType.CHAT_PANEL_CLOSED
Data payload: null
Example:
case AiChatExtensionSdkEventType.CHAT_PANEL_CLOSED:
console.log('Chat panel closed');
// Calculate session duration
const startTime = sessionTimers.get(context.tabId);
if (startTime) {
const duration = Date.now() - startTime;
analytics.track('chat_session_ended', {
durationMs: duration,
durationSeconds: Math.floor(duration / 1000),
});
sessionTimers.delete(context.tabId);
}
break;
When it fires:
- User clicks the close button on the chat panel
Event flow examples
1. User types "best running shoes" on Google Search
↓
2. QUERY_CLASSIFIED
- classification: 'shopping'
- query: 'best running shoes'
- suggestedPrompts: ['Compare running shoe brands', 'Show me deals', ...]
↓
3. CHAT_BADGE_SHOWN
- query: 'best running shoes'
- suggestedPrompts: [...]
↓
4. User clicks "Compare running shoe brands" prompt
↓
5. CHAT_BADGE_CLICKED
- prompt: 'Compare running shoe brands'
↓
6. CHAT_PANEL_OPENED
- initialMessage: 'Compare running shoe brands'
↓
7. User converses with AI, then closes panel
↓
8. CHAT_PANEL_CLOSED
Badge dismissal flow
1. User types "flights to Paris" on Google Search
↓
2. QUERY_CLASSIFIED
- classification: 'shopping'
- query: 'flights to Paris'
↓
3. CHAT_BADGE_SHOWN
- query: 'flights to Paris'
↓
4. User clicks dismiss/close on badge
↓
5. CHAT_BADGE_CLOSED
Analytics integration example
Here’s a complete example of integrating SDK events with an analytics service:
import {
getAiChatExtensionSdk,
AiChatExtensionSdkEventType,
type AiChatExtensionSdkEvent,
} from '@sleek/ai-chat-extension-sdk';
// Track session durations
const sessionTimers = new Map<number, number>();
// Register event listener
getAiChatExtensionSdk().registerEventListener((event, context) => {
const baseProperties = {
tabId: context.tabId,
url: context.url,
timestamp: Date.now(),
};
switch (event.type) {
case AiChatExtensionSdkEventType.QUERY_CLASSIFIED:
analytics.track('ai_chat_query_classified', {
...baseProperties,
classification: event.data.classification,
query: event.data.query,
isShoppingQuery: event.data.classification === 'shopping',
});
break;
case AiChatExtensionSdkEventType.CHAT_BADGE_SHOWN:
analytics.track('ai_chat_badge_shown', {
...baseProperties,
query: event.data.query,
promptCount: event.data.suggestedPrompts.length,
});
break;
case AiChatExtensionSdkEventType.CHAT_BADGE_CLICKED:
analytics.track('ai_chat_badge_clicked', {
...baseProperties,
clickedPrompt: event.data.prompt,
clickedSuggestedPrompt: !!event.data.prompt,
});
break;
case AiChatExtensionSdkEventType.CHAT_BADGE_CLOSED:
analytics.track('ai_chat_badge_dismissed', {
...baseProperties,
promptCount: event.data.suggestedPrompts.length,
});
break;
case AiChatExtensionSdkEventType.CHAT_PANEL_OPENED:
sessionTimers.set(context.tabId, Date.now());
analytics.track('ai_chat_panel_opened', {
...baseProperties,
hasInitialMessage: !!event.data.initialMessage,
initialMessage: event.data.initialMessage,
});
break;
case AiChatExtensionSdkEventType.CHAT_PANEL_CLOSED:
const startTime = sessionTimers.get(context.tabId);
const duration = startTime ? Date.now() - startTime : 0;
analytics.track('ai_chat_panel_closed', {
...baseProperties,
sessionDurationMs: duration,
sessionDurationSeconds: Math.floor(duration / 1000),
});
sessionTimers.delete(context.tabId);
break;
}
});
Debugging events
Enable debug mode to see all events logged to the console:
await initializeAiChatExtensionSdk('your-api-key', {
enableDebug: true, // Enable debug logging
// ... other options
});
You can also add a simple debug listener:
getAiChatExtensionSdk().registerEventListener((event, context) => {
console.group(`🎯 SDK Event: ${event.type}`);
console.log('Data:', event.data);
console.log('Tab:', context.tabId, context.url);
console.groupEnd();
});
Best practices
1. Track meaningful metrics
Focus on events that provide business value:
- Conversion funnel:
QUERY_CLASSIFIED → CHAT_BADGE_SHOWN → CHAT_BADGE_CLICKED → CHAT_PANEL_OPENED
- Engagement: Session durations from
CHAT_PANEL_OPENED to CHAT_PANEL_CLOSED
- Friction points:
CHAT_BADGE_CLOSED (dismissals)
2. Handle errors gracefully
Wrap event handlers in try-catch to prevent one handler from breaking others:
getAiChatExtensionSdk().registerEventListener((event, context) => {
try {
// Your event handling logic
handleEvent(event, context);
} catch (error) {
console.error('Error handling SDK event:', error);
}
});
3. Avoid blocking operations
Event handlers should be fast and non-blocking. Use async operations carefully:
getAiChatExtensionSdk().registerEventListener((event, context) => {
// Good: Fire and forget
analytics.track(event.type, event.data);
// Avoid: Blocking async operation
// await someSlowOperation();
});
4. Clean up resources
Use events to manage resources like timers:
case AiChatExtensionSdkEventType.CHAT_PANEL_CLOSED:
// Clean up session data
sessionTimers.delete(context.tabId);
sessionData.delete(context.tabId);
break;
Next steps