# Widget JavaScript API

_Category: Widget and embedding_

`window.hcWidget` lets your page drive the widget: open and close it, point it at a category or an article, hand it sign-in tokens and fire events for proactive messages. It exists as soon as `init.js` has run, and takes commands once the widget is ready.

**Plans:** All plans. `trigger()` needs proactive messages with a **Custom event** rule (Growth and Catalyst). `setJwt()` needs single sign-on (Catalyst).

## Methods

| Method | What it does | Before the widget is ready |
| --- | --- | --- |
| `show()` | Opens the widget. After `hideAll()`, also brings it back. | Lost |
| `hide()` | Closes the widget to its launcher. | Lost |
| `hideAll()` | Hides the widget, launcher included, until the next `show()`. | Works |
| `setCategory(categoryId)` | Lists a category's articles on the home screen. Doesn't open the widget. | Lost |
| `setHref(href, open)` | Loads an article, and opens the widget on it when `open` is `true`. | Lost |
| `setHrefAndOpen(href)` | The same as `setHref(href, true)`. | Lost |
| `setJwt(token)` | Hands the widget a sign-in token. | See Sign readers in, below |
| `isReady()` | Returns `true` once the widget takes commands. | Returns `false` |
| `trigger(eventName)` | Fires a custom event for proactive messages. | Queued, up to 20 events |
| `onReady(callback)` | Runs `callback` once the widget is ready, or on the next tick if it already is. | Queued |

Every method except `isReady()` returns `undefined`. None of them throws when the widget can't act on it: a lost call does nothing.

## Wait until the widget is ready

The widget becomes ready a moment after `init.js` runs, once its frame has loaded and checked that your page's host is in **Embedding origins**. On a page whose host isn't on that list, it never becomes ready. For code that should run at startup, use `onWidgetReady` in your options:

```
window.hcOptions = {
  app_id: 'YOUR_WIDGET_ID',
  onWidgetReady: function () {
    window.hcWidget.setCategory(4821);
  }
};
```

For code that runs later, such as a click handler, wrap the call in `onReady`. The check for `window.hcWidget` covers the moment before `init.js` has run:

```
if (window.hcWidget) {
  window.hcWidget.onReady(function () {
    window.hcWidget.setHrefAndOpen('/content/reset-your-password');
  });
}
```

To only check, `window.hcWidget.isReady()` returns `true` or `false`.

## Open and close the widget

```
window.hcWidget.show();    // open the widget
window.hcWidget.hide();    // close it to the launcher
window.hcWidget.hideAll(); // hide it completely, launcher included
```

After `hideAll()`, the next `show()` opens the widget; there's no call that brings back only the launcher. With the launcher on (the default), that first `show()` opens a panel only a few pixels wide. Call `show()` a second time, a moment later, to open it at full width:

```
window.hcWidget.show();
setTimeout(function () {
  window.hcWidget.show();
}, 300);
```

To keep the launcher off a page for good, use `showButton: false` in your options instead; see [Open the widget from your own UI](https://developers.helpcenter.io/content/open-the-widget-from-your-ui).

## Show a category's articles

`setCategory` takes a category ID, as a number or a string, and lists up to seven published articles from that category and its subcategories on the home screen. It doesn't open the widget, so call `show()` when you want it open:

```
window.hcWidget.setCategory(4821);
window.hcWidget.show();
```

- An ID that doesn't exist, or a category visitors can't see, lists your most viewed articles instead.
- `0`, `null` and other empty values are ignored. No call returns the home screen to its default list: reload the page for that.

Category IDs are in your help center's category addresses, `/category/4821-billing`, and in the Categories API; see [Open the widget from your own UI](https://developers.helpcenter.io/content/open-the-widget-from-your-ui).

## Open an article

`setHrefAndOpen` opens the widget on an article. `setHref` loads it for later, without opening the widget:

```
window.hcWidget.setHrefAndOpen('https://help.example.com/content/reset-your-password');

// Loaded now, shown the next time the visitor opens the widget:
window.hcWidget.setHref('/content/reset-your-password');
```

- Everything up to `/content/` is ignored, so a full article URL and a path both work. What follows `/content/` is the article's slug in your default language: a translated address, such as `/es/content/restablecer-tu-contrasena`, doesn't find the article.
- `setHref(href)` without `true` closes the widget if it's open.
- When no published article has that slug, the widget opens without it, on what it showed before.
- An address without `/content/` opens nothing, and the console logs "Unsupported content type for href."

Links on your page can do the same without code: see [Open the widget from your own UI](https://developers.helpcenter.io/content/open-the-widget-from-your-ui).

## Sign readers in

On a private help center with JWT single sign-on, the widget gets its first token from the `jwt` option and asks `onAuthExpired` for each one after that. `setJwt` hands it a token outside that exchange:

```
window.hcWidget.setJwt(tokenFromYourServer);
```

The widget uses that token in two cases only: when it has never had a token (the token then signs its next request), and when a request is waiting for a token. Otherwise it discards the token. It never reloads what it shows by itself. So when a user signs in or out while the page is open, reload the page. The complete setup is in [Sign readers into the widget with a JWT](https://developers.helpcenter.io/content/widget-jwt).

## Trigger a proactive message

A proactive message with a **Custom event** rule shows when your page fires that event. Pass the event name exactly as it's written in the rule:

```
window.hcWidget.trigger('checkout_failed');
```

Events fired before the widget is ready wait, up to 20 of them, and apply once it is. Proactive messages never show while the widget is open, or when the launcher is hidden with `showButton: false`. To see how your rules evaluate on a page, add `?hcnudge=debug` to the page's address and open the browser console. Setting up messages and rules is covered in [Invite visitors with proactive messages](https://self.helpcenter.io/content/proactive-messages).

## Callbacks

Three options in `window.hcOptions` are functions the widget calls:

| Option | Called | Details |
| --- | --- | --- |
| `onWidgetReady` | Once, when the widget is ready for commands | Wait until the widget is ready, above |
| `onContactsRequest` | When a visitor asks to contact you | [Handle contact requests yourself](https://developers.helpcenter.io/content/widget-custom-contact) |
| `onAuthExpired` | Each time the widget needs a new sign-in token | [Sign readers into the widget with a JWT](https://developers.helpcenter.io/content/widget-jwt) |

An exception thrown in `onWidgetReady` or `onAuthExpired`, or in an `onReady` callback that waited for the widget, is caught and ignored. One thrown in an `onReady` callback added after the widget is ready shows in the console as an uncaught error.

## What the API doesn't do

- **No events from the widget.** Nothing tells your page that the widget opened or closed, or that a visitor searched or read an article.
- **No removing or resetting.** There's no method to remove the widget, switch its language or return it to its first state. Reload the page.
- **No identify call.** To tell the widget who the visitor is, sign them in with a JWT.
- **No styling.** The widget's look comes from your dashboard; see [Match the widget to your brand](https://self.helpcenter.io/content/widget-appearance).

## Related

- [Widget installation and options](https://developers.helpcenter.io/content/widget-options)
- [Open the widget from your own UI](https://developers.helpcenter.io/content/open-the-widget-from-your-ui)
- [Sign readers into the widget with a JWT](https://developers.helpcenter.io/content/widget-jwt)
- [Handle contact requests yourself](https://developers.helpcenter.io/content/widget-custom-contact)
