Widget and embedding

Widget JavaScript API

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 appears a moment after init.js runs, 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

destroy()

Removes the widget from the page.

Works

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, and check for window.hcWidget first. It isn't there before init.js runs, nor for a moment after: init.js first loads a second script, for usage statistics, and only then creates window.hcWidget. So code that runs right after init.js, such as a load handler on its script tag, finds it undefined:

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.

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.

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.

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, or remove the widget and load it again with the new user's token (see Remove the widget, below). The complete setup is in Sign readers into the widget with a 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.

Remove the widget

destroy() takes the widget off your page. It removes the widget's frame, stops its proactive messages and usage statistics, and drops the trigger() events and onReady callbacks that are still waiting:

if (window.hcWidget) {
  window.hcWidget.destroy();
}
  • Links with a data-hc-article attribute become ordinary links again. FAQ sections on the page stay.

  • A second call does nothing.

  • window.hcWidget stays defined. Its commands do nothing, but if the widget was ready, isReady() still returns true and onReady() still runs a callback, so neither tells you whether a widget is on the page.

  • To put a widget back, for example when another user signs in, set window.hcOptions again and load init.js again. Call destroy() first: loading init.js again without it adds a second widget. Put the code that needs the new widget in the new options' onWidgetReady: until the new widget replaces it, window.hcWidget is still the removed one.

Callbacks

Four 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

onAuthExpired

Each time the widget needs a new sign-in token

Sign readers into the widget with a JWT

onStateChange

Many times, with true while the widget is open and false while it's closed

Below

onStateChange is called when the widget opens or closes, whether the visitor or your code opened it, and many more times in between with the same value, each time the widget redraws: while it loads, while a visitor types a search, while an answer appears. Keep the callback quick, keep the last value, and act only when it changes:

var helpIsOpen = false;

window.hcOptions = {
  app_id: 'YOUR_WIDGET_ID',
  onStateChange: function (isOpen) {
    if (isOpen === helpIsOpen) {
      return;
    }
    helpIsOpen = isOpen;
    document.getElementById('chat-button').hidden = isOpen;
  }
};

An exception thrown in onWidgetReady or onAuthExpired, or in an onReady callback that waited for the widget, is caught and ignored. One thrown in onStateChange, or 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 about what visitors do in the widget. Besides the callbacks above, nothing tells your page that a visitor searched or read an article.

  • No resetting. There's no method to switch the widget's language or return it to its first state. Remove it with destroy() and load it again, or 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.

Was this article helpful?