Skip to main content

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

Typical shopping query flow

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_CLASSIFIEDCHAT_BADGE_SHOWNCHAT_BADGE_CLICKEDCHAT_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