> ## Documentation Index
> Fetch the complete documentation index at: https://docs.onsleek.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Events

> Listen to user interactions and SDK activity with the event system

## 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:

```typescript theme={null}
import {
  getAiChatExtensionSdk,
  AiChatExtensionSdkEventType,
} from '@sleek/ai-chat-extension-sdk';

getAiChatExtensionSdk().registerEventListener((event, tabDetails) => {
  console.log('Event type:', event.type);
  console.log('Event data:', event.data);
  console.log('Tab details:', tabDetails);

  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:

```typescript theme={null}
interface AiChatExtensionSdkEvent {
  type: AiChatExtensionSdkEventType;
  data: EventData;  // Type varies by event
}

interface TabDetails {
  tabId: number;
  tabUrl: string;
}
```

* **type**: The event type (see available events below)
* **data**: Event-specific payload
* **tabDetails**: Information about the tab where the event occurred

## Chat panel events base payload

All chat panel events include a `chatSessionId` in their data payload:

```typescript theme={null}
type ChatPanelEventBasePayload = {
  chatSessionId: string;
};
```

This allows you to correlate events within the same chat session.

## Available events

### QUERY\_CLASSIFIED

Emitted when a user's query has been analyzed and classified.

**Event type**: `AiChatExtensionSdkEventType.QUERY_CLASSIFIED`

**Data payload**:

```typescript theme={null}
{
  origin: string;                   // Where the query was detected (e.g., 'google', 'chatgpt')
  query: string;                    // The query text
  classification: 'shopping' | 'unknown';
  suggestedPrompts?: string[];      // Optional suggested prompts
}
```

**Example**:

```typescript theme={null}
case AiChatExtensionSdkEventType.QUERY_CLASSIFIED:
  if (event.data.classification === 'shopping') {
    console.log(`Shopping query detected on ${event.data.origin}: "${event.data.query}"`);
    console.log('Suggested prompts:', event.data.suggestedPrompts);

    analytics.track('shopping_query_detected', {
      origin: event.data.origin,
      query: event.data.query,
      promptCount: event.data.suggestedPrompts?.length ?? 0,
    });
  }
  break;
```

### CHAT\_BADGE\_SHOWN

Emitted when the chat badge becomes visible to the user.

**Event type**: `AiChatExtensionSdkEventType.CHAT_BADGE_SHOWN`

**Data payload**:

```typescript theme={null}
{
  query: string;
  suggestedPrompts?: string[];
}
```

### 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**:

```typescript theme={null}
{
  prompt?: string;  // The specific prompt clicked, or undefined if badge itself clicked
}
```

### CHAT\_BADGE\_CLOSED

Emitted when a user dismisses the chat badge.

**Event type**: `AiChatExtensionSdkEventType.CHAT_BADGE_CLOSED`

**Data payload**:

```typescript theme={null}
{
  suggestedPrompts?: string[];
}
```

### CHAT\_PANEL\_OPENED

Emitted when the chat panel becomes visible to the user.

**Event type**: `AiChatExtensionSdkEventType.CHAT_PANEL_OPENED`

**Data payload**:

```typescript theme={null}
{
  chatSessionId: string;
  initialMessage?: string;  // The prompt or message that opened the panel
}
```

### CHAT\_PANEL\_CLOSED

Emitted when the user closes the chat panel.

**Event type**: `AiChatExtensionSdkEventType.CHAT_PANEL_CLOSED`

**Data payload**:

```typescript theme={null}
{
  chatSessionId: string;
}
```

### CHAT\_PANEL\_MESSAGE\_SENT

Emitted when the user sends a message in the chat panel.

**Event type**: `AiChatExtensionSdkEventType.CHAT_PANEL_MESSAGE_SENT`

**Data payload**:

```typescript theme={null}
{
  chatSessionId: string;
}
```

### CHAT\_PANEL\_PROMPTS\_SHOWN

Emitted when suggested prompts are displayed in the chat panel.

**Event type**: `AiChatExtensionSdkEventType.CHAT_PANEL_PROMPTS_SHOWN`

**Data payload**:

```typescript theme={null}
{
  chatSessionId: string;
  prompts: string[];
}
```

### CHAT\_PANEL\_PROMPT\_CLICKED

Emitted when the user clicks a suggested prompt in the chat panel.

**Event type**: `AiChatExtensionSdkEventType.CHAT_PANEL_PROMPT_CLICKED`

**Data payload**:

```typescript theme={null}
{
  chatSessionId: string;
  prompt: string;
}
```

### CHAT\_PANEL\_LINK\_CLICKED

Emitted when the user clicks a link in a chat message.

**Event type**: `AiChatExtensionSdkEventType.CHAT_PANEL_LINK_CLICKED`

**Data payload**:

```typescript theme={null}
{
  chatSessionId: string;
  url: string;
  merchantName?: string;
  merchantUrl?: string;
}
```

### CHAT\_PANEL\_TOP\_MERCHANTS\_SHOWN

Emitted when top merchants are displayed in the chat.

**Event type**: `AiChatExtensionSdkEventType.CHAT_PANEL_TOP_MERCHANTS_SHOWN`

**Data payload**:

```typescript theme={null}
{
  chatSessionId: string;
  merchants: string[];
}
```

### CHAT\_PANEL\_TOP\_MERCHANTS\_CLICKED

Emitted when the user clicks on a top merchant.

**Event type**: `AiChatExtensionSdkEventType.CHAT_PANEL_TOP_MERCHANTS_CLICKED`

**Data payload**:

```typescript theme={null}
{
  chatSessionId: string;
  url: string;
  merchantName?: string;
  merchantUrl?: string;
}
```

### CHAT\_PANEL\_PRODUCTS\_SHOWN

Emitted when products are displayed in the chat.

**Event type**: `AiChatExtensionSdkEventType.CHAT_PANEL_PRODUCTS_SHOWN`

**Data payload**:

```typescript theme={null}
{
  chatSessionId: string;
}
```

### CHAT\_PANEL\_PRODUCTS\_CLICKED

Emitted when the user clicks on a product.

**Event type**: `AiChatExtensionSdkEventType.CHAT_PANEL_PRODUCTS_CLICKED`

**Data payload**:

```typescript theme={null}
{
  chatSessionId: string;
  url: string;
  merchantName?: string;
  merchantUrl?: string;
}
```

### CHAT\_PANEL\_PRODUCTS\_PAGE\_NEXT\_CLICKED

Emitted when the user clicks to view the next page of products.

**Event type**: `AiChatExtensionSdkEventType.CHAT_PANEL_PRODUCTS_PAGE_NEXT_CLICKED`

**Data payload**:

```typescript theme={null}
{
  chatSessionId: string;
}
```

### CHAT\_PANEL\_PRODUCTS\_PAGE\_PREVIOUS\_CLICKED

Emitted when the user clicks to view the previous page of products.

**Event type**: `AiChatExtensionSdkEventType.CHAT_PANEL_PRODUCTS_PAGE_PREVIOUS_CLICKED`

**Data payload**:

```typescript theme={null}
{
  chatSessionId: string;
}
```

## Event flow examples

### Typical shopping query flow

```
1. User types "best running shoes" on Google Search
   ↓
2. QUERY_CLASSIFIED
   - origin: 'google'
   - 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
   - chatSessionId: 'abc123'
   - initialMessage: 'Compare running shoe brands'
   ↓
7. CHAT_PANEL_PROMPTS_SHOWN
   - chatSessionId: 'abc123'
   - prompts: ['Show top brands', 'Find deals', ...]
   ↓
8. User clicks a product link
   ↓
9. CHAT_PANEL_PRODUCTS_CLICKED
   - chatSessionId: 'abc123'
   - url: 'https://merchant.com/product'
   - merchantName: 'Merchant'
   ↓
10. User closes panel
   ↓
11. CHAT_PANEL_CLOSED
   - chatSessionId: 'abc123'
```

### Badge dismissal flow

```
1. User types "flights to Paris" on Google Search
   ↓
2. QUERY_CLASSIFIED
   - origin: 'google'
   - 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
   - suggestedPrompts: [...]
```

## Analytics integration example

Here's a complete example of integrating SDK events with an analytics service:

```typescript theme={null}
import {
  getAiChatExtensionSdk,
  AiChatExtensionSdkEventType,
  type AiChatExtensionSdkEvent,
} from '@sleek/ai-chat-extension-sdk';

// Track session durations
const sessionTimers = new Map<string, number>();

// Register event listener
getAiChatExtensionSdk().registerEventListener((event, tabDetails) => {
  const baseProperties = {
    tabId: tabDetails.tabId,
    tabUrl: tabDetails.tabUrl,
    timestamp: Date.now(),
  };

  switch (event.type) {
    case AiChatExtensionSdkEventType.QUERY_CLASSIFIED:
      analytics.track('ai_chat_query_classified', {
        ...baseProperties,
        origin: event.data.origin,
        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 ?? 0,
      });
      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 ?? 0,
      });
      break;

    case AiChatExtensionSdkEventType.CHAT_PANEL_OPENED:
      sessionTimers.set(event.data.chatSessionId, Date.now());

      analytics.track('ai_chat_panel_opened', {
        ...baseProperties,
        chatSessionId: event.data.chatSessionId,
        hasInitialMessage: !!event.data.initialMessage,
        initialMessage: event.data.initialMessage,
      });
      break;

    case AiChatExtensionSdkEventType.CHAT_PANEL_MESSAGE_SENT:
      analytics.track('ai_chat_message_sent', {
        ...baseProperties,
        chatSessionId: event.data.chatSessionId,
      });
      break;

    case AiChatExtensionSdkEventType.CHAT_PANEL_LINK_CLICKED:
      analytics.track('ai_chat_link_clicked', {
        ...baseProperties,
        chatSessionId: event.data.chatSessionId,
        url: event.data.url,
        merchantName: event.data.merchantName,
        merchantUrl: event.data.merchantUrl,
      });
      break;

    case AiChatExtensionSdkEventType.CHAT_PANEL_PRODUCTS_CLICKED:
      analytics.track('ai_chat_product_clicked', {
        ...baseProperties,
        chatSessionId: event.data.chatSessionId,
        url: event.data.url,
        merchantName: event.data.merchantName,
        merchantUrl: event.data.merchantUrl,
      });
      break;

    case AiChatExtensionSdkEventType.CHAT_PANEL_TOP_MERCHANTS_CLICKED:
      analytics.track('ai_chat_merchant_clicked', {
        ...baseProperties,
        chatSessionId: event.data.chatSessionId,
        url: event.data.url,
        merchantName: event.data.merchantName,
        merchantUrl: event.data.merchantUrl,
      });
      break;

    case AiChatExtensionSdkEventType.CHAT_PANEL_CLOSED:
      const startTime = sessionTimers.get(event.data.chatSessionId);
      const duration = startTime ? Date.now() - startTime : 0;

      analytics.track('ai_chat_panel_closed', {
        ...baseProperties,
        chatSessionId: event.data.chatSessionId,
        sessionDurationMs: duration,
        sessionDurationSeconds: Math.floor(duration / 1000),
      });

      sessionTimers.delete(event.data.chatSessionId);
      break;
  }
});
```

## Debugging events

Enable debug mode to see all events logged to the console:

```typescript theme={null}
await initializeAiChatExtensionSdk('your-api-key', {
  enableDebug: true,  // Enable debug logging
  // ... other options
});
```

You can also add a simple debug listener:

```typescript theme={null}
getAiChatExtensionSdk().registerEventListener((event, tabDetails) => {
  console.group(`🎯 SDK Event: ${event.type}`);
  console.log('Data:', event.data);
  console.log('Tab:', tabDetails.tabId, tabDetails.tabUrl);
  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, messages sent, products/merchants clicked
* **Monetization**: Track `CHAT_PANEL_LINK_CLICKED`, `CHAT_PANEL_PRODUCTS_CLICKED`, and `CHAT_PANEL_TOP_MERCHANTS_CLICKED`
* **Friction points**: `CHAT_BADGE_CLOSED` (dismissals)

### 2. Handle errors gracefully

Wrap event handlers in try-catch to prevent one handler from breaking others:

```typescript theme={null}
getAiChatExtensionSdk().registerEventListener((event, tabDetails) => {
  try {
    // Your event handling logic
    handleEvent(event, tabDetails);
  } 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:

```typescript theme={null}
getAiChatExtensionSdk().registerEventListener((event, tabDetails) => {
  // Good: Fire and forget
  analytics.track(event.type, event.data);

  // Avoid: Blocking async operation
  // await someSlowOperation();
});
```

### 4. Use chatSessionId for correlation

Use the `chatSessionId` field to correlate events within the same chat session:

```typescript theme={null}
const sessionMetrics = new Map<string, {
  opened: number;
  messageCount: number;
  linksClicked: number;
}>();

getAiChatExtensionSdk().registerEventListener((event, tabDetails) => {
  if ('chatSessionId' in event.data) {
    const sessionId = event.data.chatSessionId;

    switch (event.type) {
      case AiChatExtensionSdkEventType.CHAT_PANEL_OPENED:
        sessionMetrics.set(sessionId, {
          opened: Date.now(),
          messageCount: 0,
          linksClicked: 0,
        });
        break;

      case AiChatExtensionSdkEventType.CHAT_PANEL_MESSAGE_SENT:
        const metrics = sessionMetrics.get(sessionId);
        if (metrics) metrics.messageCount++;
        break;

      case AiChatExtensionSdkEventType.CHAT_PANEL_LINK_CLICKED:
      case AiChatExtensionSdkEventType.CHAT_PANEL_PRODUCTS_CLICKED:
        const m = sessionMetrics.get(sessionId);
        if (m) m.linksClicked++;
        break;
    }
  }
});
```
