Widget and embedding

Embed your help center in your app

Export
Download Markdown Use with AI

Show your whole help center, with its search, categories and articles, as a page of your website or app. A short script creates a frame that fits the height of each page and keeps your page's address in step with what the reader is viewing.

The embed suits a dedicated help page. To offer help next to your own interface, on any page, use the widget instead; see Widget installation and options.

Who can do this: Owners and Admins allow your website, and whoever edits your website's code adds the embed

Before you start

  • Allow the page's host. Add the host of the page that shows the help center, such as app.example.com, to Embedding origins in Settings. Until it's there, browsers refuse to show your help center in the frame. See Choose which websites can show the widget, and for how entries match, Content Security Policy and allowed origins.

  • Serve the page over HTTPS on the standard port. Browsers show the frame only on https:// pages without a port number. A page at http://localhost:3000 or http://127.0.0.1:8080 can't show it, even with its host in the list.

  • List every page in the chain. If your page is itself shown inside another page, such as a reporting tool or a website builder's custom-code frame, every host in that chain must be in Embedding origins.

Add the embed

Put this where the help center should appear, with your help center's subdomain in place of acme (for acme.helpcenter.io):

<div id="hc_embed"></div>
<script>
  var subdomain = 'acme';
</script>
<script src="https://helpcenter.io/js/embed.js"></script>
  • <div id="hc_embed"> is where the frame goes. It must come before the embed script, which looks for it when it runs. Style it like any element of your page; the frame fills its width.

  • subdomain must be a global variable, declared with var in a regular script before the embed script.

  • embed.js loads from helpcenter.io for every help center.

Help centers on a custom domain

If your help center uses a custom domain, name it in window._hcEmbedOpts:

<div id="hc_embed"></div>
<script>
  var subdomain = 'acme';
  window._hcEmbedOpts = { customDomain: 'help.acme.com' };
</script>
<script src="https://helpcenter.io/js/embed.js"></script>

Without customDomain, the frame still shows your help center, but it can't adjust its height or follow links: a help center with a custom domain moves visitors from its helpcenter.io address to the custom domain, and the embed script only listens to the address it loaded.

Setting

Where

What it does

subdomain

Global variable

Required unless you set customDomain. Your help center's subdomain, such as 'acme'.

customDomain

window._hcEmbedOpts

Required when your help center has a custom domain. The domain only, without https://, such as 'help.acme.com'. The frame loads your help center from it.

How the embed behaves

  • Height. The frame takes the height of each help center page when it loads, so visitors scroll your page as usual. Content that grows after the page has loaded isn't measured again.

  • Navigation. Links between pages of your help center open inside the frame, and your page's address follows along, for example https://app.example.com/help#/en/content/reset-your-password. Reloading or sharing that address opens the same help center page.

  • Search. Searches run inside the frame. Your page's address then shows #/search, without the search terms.

  • Links that don't open. Links to other websites, email links, and links to a heading on the same page do nothing inside the embed.

  • Your page's fragment. The embed writes to your page's URL fragment (the part after #), so it doesn't fit a page that uses the fragment for its own routing.

  • Use the script, not a plain <iframe>. In a plain frame, links inside your help center don't open.

The frame has no title, which screen readers announce. Give it one after the embed script:

<div id="hc_embed"></div>
<script>
  var subdomain = 'acme';
</script>
<script src="https://helpcenter.io/js/embed.js"></script>
<script>
  document.querySelector('#hc_embed iframe').setAttribute('title', 'Help center');
</script>

Private help centers

On a private help center, readers must be signed in inside the frame, with JWT single sign-on. How long that sign-in lasts depends on where your help center lives:

  • On your own site, it works. With a custom domain on your own domain, such as help.example.com inside app.example.com, the frame's first page sends the reader through your Login URL, and a session keeps them signed in on every page after that. Your Login URL runs inside the frame: for a reader who is already signed in to your app, it sends them straight back.

  • On another site, sign-in doesn't hold. With acme.helpcenter.io inside app.example.com, browsers don't keep the help center's session cookie in the frame. The embed script's frame never gets past sign-in: each sign-in sends it back to your Login URL, in a loop when your Login URL signs readers straight back in. A token in ?jwt= on a frame's first address signs in that page only, and the next page goes back to your Login URL. See Troubleshoot single sign-on.

For private content on a page of another site, use the widget with JWT sign-in, which sends a token with every request and needs no cookie; see Sign readers into the widget with a JWT. The embed script has no option for a token. How ?jwt= and the Login URL sign readers in is in How JWT single sign-on works.

Show the help center only inside your app

With JS-only access on, in Settings → General, your help center is shown through the embed and the widget on the websites in Embedding origins, rather than as a website of its own (see Show your help center only inside your app):

  • Opening one of its pages directly shows "Help center not available." with the status 403 Forbidden.

  • Following a link to it from a website that isn't in Embedding origins shows "Embedding not allowed."

  • The embed and the widget keep working on the websites in Embedding origins.

JS-only access keeps the help center from being browsed as a normal website, but it is not access control. To limit who can read your articles, make the help center Private and sign readers in with a JWT.

It relies on the address browsers send along with each request (the referrer). A page with Referrer-Policy: no-referrer can't show the embed: the frame shows "Help center not available." Keep at least the origin in the referrer, as the default policy, strict-origin-when-cross-origin, does.

Troubleshooting

The frame stays blank. Open the browser console. A message like this names the page the browser objected to, and lists the hosts your help center allows right now:

Framing 'https://acme.helpcenter.io/' violates the following Content Security Policy
directive: "frame-ancestors 'self' app.example.com". The request has been blocked.

Add the missing host to Embedding origins, serve the page over HTTPS on the standard port, and check the other pages around it. Changes to the list can take a couple of minutes to apply.

The frame doesn't adjust its height, and links inside it don't open. Your help center has a custom domain and the embed has no customDomain, or the page uses a plain <iframe> instead of the embed script.

The frame shows "Help center not available." JS-only access is on and your page sends no referrer. Change its Referrer-Policy.

Your page's Content Security Policy blocks the embed. Allow https://helpcenter.io in script-src and your help center's address in frame-src, plus your Login URL's origin on a private help center. See Content Security Policy and allowed origins.

Was this article helpful?