# JavaScript API

The Alhena Website SDK provides a JavaScript API for embedding and controlling the chat widget on your website. This page documents all available methods and configuration options.

## Installation

Add the following snippet to your website's HTML, replacing `company` with your company key (found in your dashboard URL after `/dashboard/`):

{% hint style="info" %}
Your company key is the word after "dashboard" in your dashboard URL. For example, if your URL is `https://app.alhena.ai/dashboard/acme/`, your company key is `acme`.
{% endhint %}

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

### Regional API URLs

Choose the base URL for your region:

| Region | Base URL                |
| ------ | ----------------------- |
| US     | `https://app.alhena.ai` |
| EU     | `https://eu.alhena.ai`  |

### Complete Installation Example

```html
<script>
document.gleenConfig = {
    company: 'acme',
    apiBaseUrl: 'https://app.alhena.ai'
};
</script>
<script src="https://app.alhena.ai/sdk/gleenWidget.js"></script>
```

You can also find your installation snippet in the Alhena dashboard under **Integrations > Website > Installation**.

***

## Quick Reference

### Methods

| Method                                                                | Description                                          |
| --------------------------------------------------------------------- | ---------------------------------------------------- |
| [`open()`](#open-options)                                             | Opens the chat widget                                |
| [`close()`](#close)                                                   | Closes the chat widget                               |
| [`toggle()`](#toggle-options)                                         | Toggles the chat widget open/closed                  |
| [`sendMessage(message)`](#sendmessage-message-options)                | Sends a message as the user                          |
| [`closeTicket()`](#closeticket)                                       | Closes the current conversation and starts a new one |
| [`getTicketId()`](#getticketid)                                       | Returns the current ticket/conversation ID           |
| [`getMessages()`](#getmessages)                                       | Returns the chat message history                     |
| [`hideLauncher()`](#hidelauncher)                                     | Hides the launcher button                            |
| [`showLauncher()`](#showlauncher)                                     | Shows the launcher button                            |
| [`showNudge(options)`](#shownudge-options)                            | Displays a proactive nudge message                   |
| [`hideNudge()`](#hidenudge)                                           | Hides any visible nudge                              |
| [`setStyles(styles)`](#setstyles-styles)                              | Updates widget styling dynamically                   |
| [`setUserMetadata(key, value)`](#setusermetadata-key-value)           | Sets a user metadata field                           |
| [`setConvertPriceHook(hook)`](#setconvertpricehook-hook)              | Sets a custom function to format product prices      |
| [`getFingerprint()`](#getfingerprint)                                 | Returns the visitor's unique fingerprint             |
| [`getFAQFingerprint()`](#getfaqfingerprint)                           | Returns the FAQ widget fingerprint                   |
| [`unload()`](#unload)                                                 | Removes the widget from the page                     |
| [`setCompanyKey(key)`](#setcompanykey-key)                            | Changes the company key dynamically                  |
| [`on(event, callback)`](#on-eventname-callback)                       | Subscribes to widget events                          |
| [`openSearch(query)`](#opensearch-query)                              | Opens the conversational search widget               |
| [`closeSearch()`](#closesearch)                                       | Closes the conversational search widget              |
| [`toggleSearch(query)`](#togglesearch-query)                          | Toggles the conversational search widget             |
| [`initializeConversationalSearch()`](#initializeconversationalsearch) | Initializes the conversational search widget         |

***

## Widget Control Methods

### open(options)

Opens the chat widget. If already open, has no effect.

**Parameters:**

| Parameter          | Type    | Required | Description                      |
| ------------------ | ------- | -------- | -------------------------------- |
| `options`          | object  | No       | Configuration options            |
| `options.expanded` | boolean | No       | Whether to open in expanded mode |

```javascript
window.gleenWidget.open();

// Open in expanded mode
window.gleenWidget.open({ expanded: true });
```

***

### close()

Closes the chat widget. If already closed, has no effect.

```javascript
window.gleenWidget.close();
```

***

### toggle(options)

Toggles the chat widget between open and closed states.

**Parameters:**

| Parameter          | Type    | Required | Description                                           |
| ------------------ | ------- | -------- | ----------------------------------------------------- |
| `options`          | object  | No       | Configuration options                                 |
| `options.expanded` | boolean | No       | Whether to open in expanded mode (when toggling open) |

```javascript
window.gleenWidget.toggle();

// Toggle with expanded mode preference
window.gleenWidget.toggle({ expanded: true });
```

***

### sendMessage(message, options)

Opens the widget and sends a message from the user's perspective. Useful for triggering conversations based on user actions.

**Parameters:**

| Parameter | Type   | Required | Description              |
| --------- | ------ | -------- | ------------------------ |
| `message` | string | Yes      | The message text to send |

```javascript
window.gleenWidget.sendMessage('I need help with my order');
```

**Use case:** Trigger a support conversation when a user clicks a "Help" button:

```javascript
document.getElementById('help-button').addEventListener('click', function() {
    window.gleenWidget.sendMessage('I need assistance');
});
```

***

## Conversation Management

### closeTicket()

Closes the current conversation/ticket and prepares the widget for a new conversation. The user will see the bot's welcome message again.

```javascript
window.gleenWidget.closeTicket();
```

**Use case:** Reset the conversation after a support interaction is complete:

```javascript
window.gleenWidget.on('ticket:agent_handoff', function() {
    setTimeout(function() {
        window.gleenWidget.closeTicket();
        window.gleenWidget.close();
    }, 60000); // Close after 1 minute
});
```

***

### getTicketId()

Returns the unique identifier for the current conversation/ticket.

**Returns:** `string | null` — the ticket ID, or `null` if no active ticket.

```javascript
const ticketId = window.gleenWidget.getTicketId();
console.log('Current ticket:', ticketId);
```

***

### getMessages()

Returns the message history for the current conversation.

**Returns:** `Array` — array of message objects.

```javascript
const messages = window.gleenWidget.getMessages();
messages.forEach(function(msg) {
    console.log(msg.role + ': ' + msg.content);
});
```

***

## Launcher Control

### hideLauncher()

Hides the floating launcher button. The widget can still be opened programmatically.

```javascript
window.gleenWidget.hideLauncher();
```

***

### showLauncher()

Shows the floating launcher button after it has been hidden.

```javascript
window.gleenWidget.showLauncher();
```

**Use case:** Show the launcher only on certain pages:

```javascript
if (window.location.pathname.includes('/support')) {
    window.gleenWidget.showLauncher();
} else {
    window.gleenWidget.hideLauncher();
}
```

***

## Nudge Messages

Nudges are proactive messages that appear near the launcher to encourage users to start a conversation.

### showNudge(options)

Displays a nudge message to the user.

**Parameters:**

| Parameter         | Type   | Required | Description                          |
| ----------------- | ------ | -------- | ------------------------------------ |
| `options.message` | string | Yes      | The nudge message text               |
| `options.delay`   | number | No       | Delay in milliseconds before showing |

```javascript
window.gleenWidget.showNudge({
    message: 'Need help finding the right product?',
    delay: 5000 // Show after 5 seconds
});
```

***

### hideNudge()

Hides any currently visible nudge message.

```javascript
window.gleenWidget.hideNudge();
```

***

## Styling

### setStyles(styles)

Dynamically updates the widget's visual appearance. See [Styles API](/docs/developer-reference/website-sdk/styles-api.md) for all available options.

```javascript
window.gleenWidget.setStyles({
    widget_position: 'LEFT',
    bottom_spacing: 20,
    right_spacing: 20,
    widget_border_radius: 16
});
```

***

## User Data

### setUserMetadata(key, value)

Sets a single user metadata field for personalization. Call multiple times to set multiple fields. See [Custom Data](/docs/developer-reference/website-sdk/custom-data.md) for details.

**Parameters:**

| Parameter | Type   | Required | Description                         |
| --------- | ------ | -------- | ----------------------------------- |
| `key`     | string | Yes      | The metadata key to set             |
| `value`   | any    | Yes      | The value to associate with the key |

```javascript
window.gleenWidget.setUserMetadata('email', 'user@example.com');
window.gleenWidget.setUserMetadata('name', 'John Doe');
window.gleenWidget.setUserMetadata('plan', 'premium');
```

{% hint style="info" %}
Keys starting with `_` (underscore) are private and not exposed to the AI. Use these for sensitive data like API tokens.
{% endhint %}

***

## Price Conversion

### setConvertPriceHook(hook)

Sets a custom function to format product prices before they are displayed in the widget. Useful for currency conversion or localized formatting. Can also be set at initialization via `document.gleenConfig.convertPrice`.

**Parameters:**

| Parameter | Type     | Required | Description                                                              |
| --------- | -------- | -------- | ------------------------------------------------------------------------ |
| `hook`    | function | Yes      | Receives `(price, { variantId })` and returns the formatted price string |

```javascript
window.gleenWidget.setConvertPriceHook(function(price, metadata) {
    const amount = parseFloat(price.replace(/[^0-9.]/g, ''));
    return '€' + (amount * 0.85).toFixed(2);
});
```

See [Price Conversion Examples](/docs/developer-reference/website-sdk/examples/price-conversion.md) for more usage patterns.

***

## Analytics & Tracking

### getFingerprint()

Returns the visitor's unique fingerprint identifier, used for analytics and session tracking.

**Returns:** `string` — UUID fingerprint.

```javascript
const fingerprint = window.gleenWidget.getFingerprint();
```

***

### getFAQFingerprint()

Returns the [Product FAQ](/docs/features/product-faqs.md) widget's fingerprint identifier.

**Returns:** `string` — UUID fingerprint.

```javascript
const faqFingerprint = window.gleenWidget.getFAQFingerprint();
```

***

## Widget Lifecycle

### unload()

Completely removes the widget from the page. Useful for single-page applications when navigating away from pages where the widget should appear.

```javascript
window.gleenWidget.unload();
```

***

### setCompanyKey(key)

Changes the company key dynamically. This reloads the widget with the new company's configuration.

**Parameters:**

| Parameter | Type   | Required | Description         |
| --------- | ------ | -------- | ------------------- |
| `key`     | string | Yes      | The new company key |

```javascript
window.gleenWidget.setCompanyKey('different-company');
```

***

## Event Subscription

### on(eventName, callback)

Subscribes to widget events. See [Events](/docs/developer-reference/website-sdk/events.md) for a complete list of available events.

**Parameters:**

| Parameter   | Type     | Required | Description                      |
| ----------- | -------- | -------- | -------------------------------- |
| `eventName` | string   | Yes      | The event name to listen for     |
| `callback`  | function | Yes      | Function called when event fires |

```javascript
window.gleenWidget.on('widget:opened', function() {
    console.log('Widget was opened');
});

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

***

## Conversational Search Methods

These methods control the [Conversational Search](/docs/features/conversational-search.md) widget. The search widget must be set up on your page before these methods will work — see the [Conversational Search setup guide](/docs/features/conversational-search.md) for installation steps.

### openSearch(query)

Opens the conversational search widget. Optionally sends a query immediately.

**Parameters:**

| Parameter | Type   | Required | Description                                                  |
| --------- | ------ | -------- | ------------------------------------------------------------ |
| `query`   | string | No       | A search query to submit automatically when the widget opens |

```javascript
// Open search
window.gleenWidget.openSearch();

// Open search and submit a query
window.gleenWidget.openSearch("running shoes under $100");
```

**Use case:** Connect to your existing search bar so users can switch to AI-powered search:

```javascript
document.querySelector('.ai-search-button').addEventListener('click', function() {
    var searchInput = document.querySelector('#search-input');
    window.gleenWidget.openSearch(searchInput.value);
    searchInput.value = '';
});
```

***

### closeSearch()

Closes the conversational search widget.

```javascript
window.gleenWidget.closeSearch();
```

***

### toggleSearch(query)

Toggles the conversational search widget open or closed. When opening, optionally sends a query.

**Parameters:**

| Parameter | Type   | Required | Description                                    |
| --------- | ------ | -------- | ---------------------------------------------- |
| `query`   | string | No       | A search query to submit when the widget opens |

```javascript
window.gleenWidget.toggleSearch();

// Toggle open with a query
window.gleenWidget.toggleSearch("blue dresses");
```

***

### initializeConversationalSearch()

Manually initializes the conversational search widget. The SDK automatically calls this on page load if the `#alhena-conversational-search` div is present. Use this method if you add the div dynamically after page load (e.g., in a single-page application).

```javascript
// After dynamically adding <div id="alhena-conversational-search"></div>
window.gleenWidget.initializeConversationalSearch();
```

***

## Configuration Options

Configure the widget by setting `document.gleenConfig` before loading the SDK script.

### Basic Configuration

```javascript
document.gleenConfig = {
    company: 'your-company-key',
    apiBaseUrl: 'https://app.alhena.ai'
};
```

### Full Configuration Example

```javascript
document.gleenConfig = {
    company: 'your-company-key',
    apiBaseUrl: 'https://app.alhena.ai',

    // Styling
    styles: {
        widget_position: 'RIGHT',
        bottom_spacing: 20,
        right_spacing: 20,
        widget_border_radius: 16,
        fontFamily: 'Inter, sans-serif'
    },

    // User data
    userMetadata: {
        email: 'user@example.com',
        name: 'John Doe',
        _api_token: 'secret-token' // Private, not sent to AI
    },

    // Localization
    locale: 'es', // Spanish

    // Behavior
    defaultExpanded: false,
    hideLauncher: false,
    ticket_mode: 'NORMAL' // or 'BOT_ONLY'
};
```

### Configuration Options Reference

| Option             | Type     | Default    | Description                              |
| ------------------ | -------- | ---------- | ---------------------------------------- |
| `company`          | string   | -          | Your company key (required)              |
| `apiBaseUrl`       | string   | -          | Regional API URL (required)              |
| `styles`           | object   | `{}`       | Widget styling options                   |
| `userMetadata`     | object   | `{}`       | User data for personalization            |
| `locale`           | string   | auto       | Language code (e.g., 'en', 'es', 'fr')   |
| `defaultExpanded`  | boolean  | `false`    | Open widget on page load                 |
| `hideLauncher`     | boolean  | `false`    | Hide the launcher button                 |
| `showExpandButton` | boolean  | `true`     | Show button to expand widget             |
| `ticket_mode`      | string   | `'NORMAL'` | `'NORMAL'` or `'BOT_ONLY'`               |
| `convertPrice`     | function | -          | Custom function to format product prices |

***

## Complete Example

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Alhena Chat Widget Example</title>
</head>
<body>

<h1>Welcome to Our Store</h1>
<button id="help-btn">Get Help</button>
<button id="close-btn">Close Chat</button>

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

<!-- Widget Control -->
<script>
// Button handlers
document.getElementById('help-btn').addEventListener('click', function() {
    window.gleenWidget.open();
});

document.getElementById('close-btn').addEventListener('click', function() {
    window.gleenWidget.close();
});

// Event listeners
window.gleenWidget.on('widget:loaded', function() {
    console.log('Chat widget ready');
});

window.gleenWidget.on('widget:opened', function() {
    console.log('Chat opened');
});

window.gleenWidget.on('ticket:agent_handoff', function() {
    console.log('Transferred to human agent');
});
</script>

</body>
</html>
```

***

## Related Resources

* [Events Reference](/docs/developer-reference/website-sdk/events.md) - Complete list of widget events
* [Styles API](/docs/developer-reference/website-sdk/styles-api.md) - Customizing widget appearance
* [Custom Data](/docs/developer-reference/website-sdk/custom-data.md) - Passing user data to the widget
* [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/javascript-api.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.
