# Events

The Alhena Website SDK emits JavaScript events that allow you to respond to user interactions and widget state changes. Use these events to customize the user experience, track analytics, or integrate with other systems.

## Subscribing to Events

Use the `window.gleenWidget.on()` method to subscribe to events:

```javascript
window.gleenWidget.on('event_name', function(data) {
    // Handle the event
    console.log('Event fired:', data);
});
```

{% hint style="info" %}
Event subscriptions should be set up after the SDK script loads. For best results, place your event handlers after the SDK script tag or inside a `widget:loaded` handler.
{% endhint %}

***

## Quick Reference

| Event                                                               | Category   | Description                               |
| ------------------------------------------------------------------- | ---------- | ----------------------------------------- |
| [`widget:loaded`](#widget-loaded)                                   | Widget     | Widget finished loading                   |
| [`widget:opened`](#widget-opened)                                   | Widget     | Widget was opened                         |
| [`widget:closed`](#widget-closed)                                   | Widget     | Widget was closed                         |
| [`ticket:message_submitted`](#ticket-message_submitted)             | Ticket     | User sent a message                       |
| [`ticket:bot_response_finished`](#ticket-bot_response_finished)     | Ticket     | Bot completed its response                |
| [`ticket:agent_handoff`](#ticket-agent_handoff)                     | Ticket     | Ticket transferred to human agent         |
| [`ticket:agent_handoff_initiated`](#ticket-agent_handoff_initiated) | Ticket     | Human handoff process started             |
| [`ticket:link_clicked`](#ticket-link_clicked)                       | Ticket     | User clicked a link in chat               |
| [`ticket:input_focused`](#ticket-input_focused)                     | Ticket     | User focused the input field              |
| [`ticket:attachment_added`](#ticket-attachment_added)               | Ticket     | User attached a file                      |
| [`ticket:closed`](#ticket-closed)                                   | Ticket     | Conversation was closed                   |
| [`ticket:email_submitted`](#ticket-email_submitted)                 | Ticket     | User submitted their email during handoff |
| [`ticket:quiz_options_rendered`](#ticket-quiz_options_rendered)     | Ticket     | Quiz option buttons were displayed        |
| [`product:added_to_cart`](#product-added_to_cart)                   | E-commerce | User clicked "Add to Cart"                |
| [`products:added_to_cart`](#products-added_to_cart)                 | E-commerce | Multiple products added to cart           |
| [`product:page_opened`](#product-page_opened)                       | E-commerce | User clicked a product link               |
| [`product:displayed`](#product-displayed)                           | E-commerce | Product card was rendered                 |
| [`faqs:question_clicked`](#faqs-question_clicked)                   | FAQ        | User clicked a FAQ question               |
| [`faqs:message_submitted`](#faqs-message_submitted)                 | FAQ        | User submitted a FAQ question             |
| [`faqs:bot_response_finished`](#faqs-bot_response_finished)         | FAQ        | Bot finished FAQ response                 |
| [`faqs:link_clicked`](#faqs-link_clicked)                           | FAQ        | User clicked a link in a FAQ response     |
| [`experiment:loaded`](#experiment-loaded)                           | Experiment | A/B test group assigned                   |
| [`icebreaker_question:postback`](#icebreaker_question-postback)     | Widget     | User clicked an icebreaker                |

***

## Widget Events

Events related to the widget's state and lifecycle.

### widget:loaded

Fired when the widget has finished loading and is ready for interaction. Use this event to safely set up other event handlers or perform initial configuration.

**Callback data:** None

```javascript
window.gleenWidget.on('widget:loaded', function() {
    console.log('Widget is ready');
    // Safe to call other widget methods now
    window.gleenWidget.showNudge({
        message: 'Need help? Ask me anything!'
    });
});
```

***

### widget:opened

Fired when the chat widget is opened (expanded).

**Callback data:** None

```javascript
window.gleenWidget.on('widget:opened', function() {
    console.log('User opened the chat widget');
    // Track in analytics
    gtag('event', 'chat_opened');
});
```

***

### widget:closed

Fired when the chat widget is closed (minimized).

**Callback data:** None

```javascript
window.gleenWidget.on('widget:closed', function() {
    console.log('User closed the chat widget');
});
```

***

## Ticket/Conversation Events

Events related to chat conversations and messages.

### ticket:message\_submitted

Fired when the user sends a message in the chat widget.

**Callback data:**

| Property       | Type   | Description                                                                     |
| -------------- | ------ | ------------------------------------------------------------------------------- |
| `text`         | string | The message text sent by the user                                               |
| `submitAction` | string | How the message was sent: `button_click`, `enter_key`, or `quiz_option_clicked` |

```javascript
window.gleenWidget.on('ticket:message_submitted', function(data) {
    console.log('User sent:', data.text);
});
```

***

### ticket:bot\_response\_finished

Fired when the AI bot has finished generating and streaming its response.

**Callback data:**

| Property | Type   | Description                    |
| -------- | ------ | ------------------------------ |
| `text`   | string | The complete bot response text |

```javascript
window.gleenWidget.on('ticket:bot_response_finished', function(data) {
    console.log('Bot responded:', data.text);
});
```

***

### ticket:agent\_handoff

Fired when a ticket has been successfully created in the helpdesk system after the user submits their email during human handoff.

**Callback data:**

| Property   | Type   | Description                  |
| ---------- | ------ | ---------------------------- |
| `ticketId` | string | The ID of the created ticket |
| `email`    | string | The user's email address     |

```javascript
window.gleenWidget.on('ticket:agent_handoff', function(data) {
    console.log('Ticket created:', data.ticketId);
    console.log('User email:', data.email);

    // Optionally close the widget after handoff
    setTimeout(function() {
        window.gleenWidget.close();
    }, 5000);
});
```

***

### ticket:agent\_handoff\_initiated

Fired when the AI determines that the conversation should be transferred to a human agent. At this stage, the AI is waiting for the user to submit their email address.

**Callback data:** None

```javascript
window.gleenWidget.on('ticket:agent_handoff_initiated', function() {
    console.log('Human handoff started - waiting for user email');

    // Example: Switch to another support widget
    // window.gleenWidget.closeTicket();
    // window.gleenWidget.close();
    // loadAlternativeSupportWidget();
});
```

***

### ticket:link\_clicked

Fired when the user clicks a link within a chat message.

**Callback data:**

| Property | Type   | Description              |
| -------- | ------ | ------------------------ |
| `url`    | string | The URL that was clicked |
| `text`   | string | The link text            |

```javascript
window.gleenWidget.on('ticket:link_clicked', function(data) {
    console.log('User clicked link:', data.url);
    // Track outbound link clicks
});
```

***

### ticket:input\_focused

Fired when the user focuses on the message input field.

**Callback data:** None

```javascript
window.gleenWidget.on('ticket:input_focused', function() {
    console.log('User is about to type a message');
});
```

***

### ticket:attachment\_added

Fired when the user attaches a file to their message.

**Callback data:**

| Property   | Type   | Description               |
| ---------- | ------ | ------------------------- |
| `fileName` | string | Name of the attached file |
| `fileType` | string | MIME type of the file     |
| `fileSize` | number | Size in bytes             |

```javascript
window.gleenWidget.on('ticket:attachment_added', function(data) {
    console.log('User attached:', data.fileName);
});
```

***

### ticket:closed

Fired when a conversation is closed.

**Callback data:**

| Property    | Type   | Description                 |
| ----------- | ------ | --------------------------- |
| `ticket_id` | string | The ID of the closed ticket |

```javascript
window.gleenWidget.on('ticket:closed', function(data) {
    console.log('Conversation closed:', data.ticket_id);
});
```

***

### ticket:email\_submitted

Fired when the user submits their email address during the human handoff flow, before the ticket is created in the helpdesk.

**Callback data:**

| Property | Type   | Description                             |
| -------- | ------ | --------------------------------------- |
| `email`  | string | The email address submitted by the user |

```javascript
window.gleenWidget.on('ticket:email_submitted', function(data) {
    console.log('User submitted email:', data.email);
});
```

***

### ticket:quiz\_options\_rendered

Fired when [quiz option](/docs/features/chat-widget/quiz-options.md) buttons are displayed in the conversation.

**Callback data:**

| Property    | Type   | Description                                  |
| ----------- | ------ | -------------------------------------------- |
| `options`   | array  | Array of option strings shown to the user    |
| `messageId` | string | The ID of the message containing the options |

```javascript
window.gleenWidget.on('ticket:quiz_options_rendered', function(data) {
    console.log('Quiz options shown:', data.options);
});
```

***

## E-commerce Events

Events for e-commerce integrations. These events help you connect the chat widget with your shopping cart and product pages.

{% hint style="info" %}
**Important:** By adding an event handler for the `product:added_to_cart` event, you will cause the "Add to Cart" button to appear in product cards. You must implement custom JavaScript specific to your e-commerce platform to handle this event.
{% endhint %}

### product:added\_to\_cart

Fired when a customer clicks the "Add to Cart" button on a product card within the chat widget.

**Callback data:**

| Property    | Type   | Description                 |
| ----------- | ------ | --------------------------- |
| `variantId` | string | The product variant ID      |
| `productId` | string | The product ID              |
| `quantity`  | number | Quantity to add (usually 1) |
| `price`     | number | Product price               |

```javascript
window.gleenWidget.on('product:added_to_cart', function(data) {
    console.log('Add to cart - Variant:', data.variantId);
    console.log('Quantity:', data.quantity);

    // Example: Add to Shopify cart via AJAX
    fetch('/cart/add.js', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            id: data.variantId,
            quantity: data.quantity
        })
    }).then(function() {
        // Show cart drawer or redirect to cart
        openCartDrawer();
    });
});
```

***

### products:added\_to\_cart

Fired when multiple products are added to cart at once (e.g., from a product bundle or quiz results).

**Callback data:**

| Property   | Type  | Description              |
| ---------- | ----- | ------------------------ |
| `products` | array | Array of product objects |

Each product object contains:

| Property    | Type   | Description            |
| ----------- | ------ | ---------------------- |
| `variantId` | string | The product variant ID |
| `productId` | string | The product ID         |
| `quantity`  | number | Quantity to add        |

```javascript
window.gleenWidget.on('products:added_to_cart', function(data) {
    console.log('Adding multiple products:', data.products.length);

    data.products.forEach(function(product) {
        // Add each product to your cart
        addToCart(product.variantId, product.quantity);
    });
});
```

***

### product:page\_opened

Fired when a customer clicks a product link rendered inside the chat widget.

**Callback data:**

| Property    | Type   | Description            |
| ----------- | ------ | ---------------------- |
| `variantId` | string | The product variant ID |
| `productId` | string | The product ID         |
| `url`       | string | The product page URL   |

```javascript
window.gleenWidget.on('product:page_opened', function(data) {
    console.log('User opened product:', data.variantId);
    // Optionally track product views
});
```

***

### product:displayed

Fired when a product card is rendered inside the chat widget.

**Callback data:**

| Property    | Type   | Description            |
| ----------- | ------ | ---------------------- |
| `variantId` | string | The product variant ID |
| `productId` | string | The product ID         |

```javascript
window.gleenWidget.on('product:displayed', function(data) {
    console.log('Product displayed:', data.variantId);
    // Track product impressions
});
```

***

## FAQ Events

Events for the [Product FAQ](/docs/features/product-faqs.md) feature.

### faqs:question\_clicked

Fired when a user clicks on an AI-generated FAQ question.

**Callback data:**

| Property | Type   | Description       |
| -------- | ------ | ----------------- |
| `text`   | string | The question text |

```javascript
window.gleenWidget.on('faqs:question_clicked', function(data) {
    console.log('FAQ question clicked:', data.text);
});
```

***

### faqs:message\_submitted

Fired when a user submits a custom question in the product FAQ text box.

**Callback data:**

| Property       | Type   | Description                                                                     |
| -------------- | ------ | ------------------------------------------------------------------------------- |
| `text`         | string | The user's question                                                             |
| `submitAction` | string | How the message was sent: `button_click`, `enter_key`, or `quiz_option_clicked` |

```javascript
window.gleenWidget.on('faqs:message_submitted', function(data) {
    console.log('FAQ question asked:', data.text);
});
```

***

### faqs:bot\_response\_finished

Fired when the AI completes its response in the FAQ widget. This applies to both clicked FAQ questions and custom user questions.

**Callback data:**

| Property | Type   | Description                |
| -------- | ------ | -------------------------- |
| `text`   | string | The AI's complete response |

```javascript
window.gleenWidget.on('faqs:bot_response_finished', function(data) {
    console.log('FAQ response:', data.text);
});
```

***

### faqs:link\_clicked

Fired when a user clicks a link within a FAQ response.

**Callback data:**

| Property | Type   | Description              |
| -------- | ------ | ------------------------ |
| `url`    | string | The URL that was clicked |

```javascript
window.gleenWidget.on('faqs:link_clicked', function(data) {
    console.log('FAQ link clicked:', data.url);
});
```

***

## Experiment Events

Events for A/B testing functionality.

### experiment:loaded

Fired when an active A/B test experiment is running and the user has been assigned to a group. See [A/B Testing](/docs/developer-reference/website-sdk/ab-testing.md) for full documentation.

**Callback data:** `string` — either `'test'` or `'control'`

```javascript
window.gleenWidget.on('experiment:loaded', function(experimentGroup) {
    console.log('User assigned to:', experimentGroup);
    // experimentGroup is 'test' or 'control'

    if (experimentGroup === 'control') {
        // Load alternative support solution for control group
        loadZendeskWidget();
    }
});
```

***

## Icebreaker Events

Events related to conversation starters and quick replies.

### icebreaker\_question:postback

Fired when a user clicks an icebreaker question or quick reply button.

**Callback data:**

| Property           | Type   | Description                  |
| ------------------ | ------ | ---------------------------- |
| `question_text`    | string | The icebreaker question text |
| `type`             | string | The type of icebreaker       |
| `postback_payload` | string | The postback payload value   |

```javascript
window.gleenWidget.on('icebreaker_question:postback', function(data) {
    console.log('Icebreaker clicked:', data.question_text);
});
```

***

## Complete Example

Here's a complete example showing how to set up multiple event handlers:

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Alhena Events Example</title>
</head>
<body>

<!-- Alhena SDK -->
<script>
document.gleenConfig = {
    company: 'your-company-key',
    apiBaseUrl: 'https://app.alhena.ai'
};
</script>
<script src="https://app.alhena.ai/sdk/gleenWidget.js"></script>

<script>
// Widget lifecycle events
window.gleenWidget.on('widget:loaded', function() {
    console.log('Chat widget ready');
});

window.gleenWidget.on('widget:opened', function() {
    gtag('event', 'chat_widget_opened');
});

window.gleenWidget.on('widget:closed', function() {
    gtag('event', 'chat_widget_closed');
});

// Conversation events
window.gleenWidget.on('ticket:message_submitted', function(data) {
    gtag('event', 'chat_message_sent', {
        message_length: data.text.length
    });
});

window.gleenWidget.on('ticket:agent_handoff', function(data) {
    gtag('event', 'human_handoff_completed', {
        ticket_id: data.ticketId
    });
});

// E-commerce events
window.gleenWidget.on('product:added_to_cart', function(data) {
    // Add to your cart
    addToCart(data.variantId, data.quantity);

    // Track in analytics
    gtag('event', 'add_to_cart', {
        currency: 'USD',
        items: [{
            item_id: data.productId,
            item_variant: data.variantId,
            quantity: data.quantity
        }]
    });
});

// A/B testing
window.gleenWidget.on('experiment:loaded', function(experimentGroup) {
    gtag('event', 'experiment_assigned', {
        experiment_group: experimentGroup
    });
});
</script>

</body>
</html>
```

***

## Related Resources

* [JavaScript API](/docs/developer-reference/website-sdk/javascript-api.md) - Complete method reference
* [A/B Testing](/docs/developer-reference/website-sdk/ab-testing.md) - Experiment setup and events
* [Cart & Checkout Events](/docs/developer-reference/website-sdk/cart-checkout-events.md) - Revenue tracking
* [Examples](/docs/developer-reference/website-sdk/examples.md) - Code examples for common use cases


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://alhena.gitbook.io/docs/developer-reference/website-sdk/events.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
