Dynamic Table of Contents for WP Posts

Dynamic Table of Contents for WP Posts

Learn how to dynamically add a Table of Contents to WP posts using filters and modify single templates for full functionality.

Home / Blog / Wordpress / Dynamic Table of Contents for WP Posts

A dynamic Table of Contents (TOC) improves navigation and readability for long-form WordPress content. Using the the_content filter and a user-controlled option, you can insert a TOC automatically before your post content. Here’s how to do it step by step.

Step 1: Add the TOC Logic to functions.php

This snippet dynamically generates and inserts a TOC based on the post’s headings (<h1> to <h6>):

// Check if the Table of Contents option is enabled
$enable_toc = get_option('_horizon_enable_toc', false);

if ($enable_toc) {
    // Hook the function to 'the_content' filter to modify post content
    add_filter('the_content', 'horizon_generate_toc', 10, 1);
}

/**
 * Generate a Table of Contents from the content.
 *
 * @param string $content The post content.
 * @return string Modified content with a table of contents.
 */
function horizon_generate_toc($content) { 
    // Match all headings in the content (h1, h2, h3, etc.)
    preg_match_all('/<h([1-6])[^>]*>(.*?)<\/h[1-6]>/', $content, $matches, PREG_SET_ORDER);

    if (empty($matches)) {
        return $content; // No headings found, return content as is
    }

    // Start building the Table of Contents
    $toc = '<div class="toc"><h2>Table of Contents</h2><ul>';

    foreach ($matches as $match) {
        $level = $match[1]; // Heading level (1-6)
        $heading_text = strip_tags($match[2]); // Heading content
        $id = sanitize_title($heading_text); // Generate a URL-friendly ID

        // Add an ID to the heading tag for anchor linking
        $content = str_replace($match[0], '<h' . $level . ' id="' . $id . '">' . $match[2] . '</h' . $level . '>', $content);

        // Add the heading to the TOC list
        $toc .= '<li class="toc-level-' . $level . '"><a href="#' . $id . '">' . $heading_text . '</a></li>';
    }

    $toc .= '</ul></div>';

    // Insert the TOC at the beginning of the content
    $content = $toc . $content;

    return $content;
}

Step 2: Enable or Disable the TOC Option in WordPress

To give users control, add a toggle option in the WordPress admin. Use the following code to register the setting:

// Add a TOC option in the Settings > General page
add_action('admin_init', function() {
    register_setting('general', '_horizon_enable_toc');
    add_settings_field(
        '_horizon_enable_toc',
        'Enable Table of Contents',
        function() {
            $value = get_option('_horizon_enable_toc', false);
            echo '<input type="checkbox" name="_horizon_enable_toc" value="1"' . checked(1, $value, false) . '> Enable';
        },
        'general'
    );
});

This creates a checkbox in the Settings > General page. When checked, the TOC will be enabled.

Step 3: Ensure Your Single Template Supports Filters

To apply the the_content filter, your single.php template must include the WordPress loop. Add this to your theme if it’s missing:

if ( have_posts() ) {
    while ( have_posts() ) {
        the_post();
        the_content(); // Outputs filtered content with the TOC
    }
}

Conclusion

With the above setup, you can dynamically insert a Table of Contents for WordPress posts using the the_content filter. By adding a toggle option, you provide users the flexibility to enable or disable the TOC as needed. This approach ensures enhanced navigation, improved SEO, and better user experience.