Toolsby Spectral Web Services

DocsWidgets

Table of Contents

How the contents list gets into a post, the one-time setup, the marker to place, and why a post that sends an email has to be scheduled rather than published.

How it works

When a post is published or scheduled, a webhook collects its h2 and h3 headings, builds a clickable contents list, and replaces a marker in the post body with it. It's rebuilt every time the post is published again, so it stays right when you edit.

Paywalls. The list includes every heading in the post, the ones behind the paywall included, so a reader without access can see what the rest of the article covers. On your site, clicking one of those headings opens your upgrade call to action: the theme's own, if it has one, or a "paid subscribers only" box with an Upgrade link. That behaviour comes from the code injection snippet below, along with the list's styling.

Email and ActivityPub. Because the list is written into the post itself, it's in the email Ghost sends and in ActivityPub readers too. From either, a click brings the reader to the post on your website, at that heading.

One-time setup

  1. Tick Enable TOC webhook for this site. It's a site setting, so a site admin does this once.
  2. In Ghost, open Settings → Integrations and pick an existing custom integration or create one. Add a webhook with the event Post published, the name SWS Table of Contents, the Webhook URL shown on the page, and the webhook secret shown beside it. Add a second webhook with the event Post scheduled, same name, URL and secret.
  3. Open Settings → Code injection and paste the Code injection snippet into the Site Header. It styles the list on your site; email gets a plain version.

Lost the secret? reveals it again; Rotate issues a new one, after which both webhooks in Ghost need the new value.

Using it in a post

In any post that should have a contents list, add an HTML card containing <div id="sws-toc-insertion-target"></div> where the list should appear, usually under the intro. A post without the marker is left alone.

Then publish or schedule, and the difference matters:

  • Scheduled posts get their contents list while they wait, so it's in place when the post goes live and when the email sends.
  • Posts published immediately are edited a few minutes later to add the list. That's fine for the web. But an email goes out at the moment you publish, before the list exists, so any post that sends an email has to be scheduled, even just a few minutes ahead. Otherwise the email arrives without the table of contents.

The Newsletter Digests tool has its own Table of contents section that needs none of this, since it builds the list as it assembles the issue.