Simple Table of Content (ToC) for pages

I was trying to find a simple way to add a table of content to an individual page in Ghost

The following code works perfectly for me.

Just paste the code directly into the actual page (using the ‘HTML’ element) below your title and above where your content will start.

I have it set to just add H2 items, but I’m sure it can be adjusted. You can also edit some of the display settings as you wish.

I haven’t tried it on ‘posts’ (as I already have that installed in the theme)

Hopefully this is useful to someone

<div id="toc-placeholder">
        window.addEventListener('DOMContentLoaded', function () {
            const tocContainer = document.createElement('div');
   = 'toc';
            tocContainer.innerHTML = '<h2>Table of Contents</h2><ul>';

            const h2Elements = document.querySelectorAll('h2');
            h2Elements.forEach(h2 => {
                const listItem = document.createElement('li');
                const link = document.createElement('a');
                link.href = '#' +;  // Ensure "#" before the ID
                link.textContent = h2.textContent;

            const placeholder = document.getElementById('toc-placeholder');
            placeholder.parentNode.replaceChild(tocContainer, placeholder);

        #toc {
            background-color: #f0f0f0;
            padding: 20px;
            border: 1px solid #ccc;

        #toc ul {
            list-style-type: none;
            margin: 0;
            padding: 0;

        #toc a {
            color: #333;
            text-decoration: none;

Cool, would this work for non-self hosted Ghost accounts?

It should work, yes. Haven’t tried it myself, but what @Ian_R is proposing is simply pasting the code into a HTML card directly in the editor.

Here’s one that I use - GitHub - Trizone-media/toc: Place an on-page table of contents that dynamically changes based on headings