• Skip to main content
  • Skip to primary sidebar
  • Skip to footer

nSiteful Web Builders

Building a Better Web - One Site at a Time.

  • Home
  • About
    • Testimonials
    • Resources
    • Partner With Me
    • Frequently Asked Questions
  • Web Sites
  • Online Marketing
  • WordPress Support
    • Customized WordPress Training
    • 60-for-60 Sessions
  • Web Applications
  • Blog
    • At-A-Glance
    • Blog Articles Grouped by Category
    • Case Studies
    • General
    • Portfolio
    • Reviews
    • Snippets
    • Techniques
  • Contact
    • Purchase Retainer Consulting Hours
    • About Retainer Consulting Hours
    • Book a Meeting with Jeff
    • Tell Me About Your Web Project
    • nSiteful Newsletter Archives
    • nSiteful Rewards

By Jeff - 11/11/2018
Cats: Techniques · Tags: Shortcodes, WordPress

techniques

Add Dynamic Table of Contents to a Series of WordPress Posts

Last updated November 15th, 2018 at 09:11 am

When I’m writing a series of posts on a subject — such as a multi-part tutorial — I like to include a table of contents for that series of posts. I think this helps readers navigate the content.

Here’s what I’m talking about:

I’ve searched unsuccessfully* for a plugin that would make this process easier than my old standard process:

(* Spoke too soon. See Update below for some plugins I found after publishing this post.)

My old standard process: As soon as I was publishing the second post in the series, I would manually hard-code a block of HTML with the title and permalink of each post and paste it in the desired place (usually up near the top) of each post. When I publish a new post in the series, I’d edit that HTML block, adding the permalink and title of the new post, paste that new HTML into the new post, and replace the HTML blocks in all the previous posts with the new HTML block. And so on.

There’s got to be a better way!

So, having failed to find a plugin, I patched together my own method. It’s not (yet) a distributable plugin. But maybe some day it will be, unless one already exists.

The solution I’ve come up with consists of two primary components:

  • A custom shortcode that generates the necessary HTML
  • the amr shortcode any widget plugin

The Custom Shortcode

function nwb_shortcode_toc($atts) {
	global $post;
	$atts = shortcode_atts( array(
		'ids' => '',
	), $atts, 'nwbtoc' );
	if ( empty($atts['ids']) ) {
		return;
	}
	$ids = $atts['ids'];
	$id_array = explode(',', $ids);
	$output = '<div class="nwb-toc">';
	$output .= '<h2>Posts in this Series</h2>';
	$output .= '<ol>';
	foreach ( $id_array as $id ) {
		$curr_other = ( $id == $post->ID ) ? 'current' : 'other' ;
		$output .= '<li class="' . $curr_other . '"><a href="' . get_permalink($id) . '">' . get_the_title($id) . '</a></li>';
	}
	$output .= '</ol>';
	$output .= '</div>';
	return $output;
}
add_shortcode('nwbtoc', 'nwb_shortcode_toc');

The shortcode would look like this when entered into a post:

[[nwbtoc ids="4327,4446"]]

The ‘ids’ parameter is a comma-separated list of post ID numbers.

The code in Line 15 tests whether the current item in the foreach loop corresponds to the “current” post. If it does, its li tag is given the class of “current”, which allows me to use CSS to change how that item is rendered. (Namely, I remove the text-decoration and change the cursor to “default”, so as to discourage the reader from clicking on the link for a post s/he’s currently reading.)

PS: I might extend to plugin to support variable h2 text as well as formatting of the list. Maybe later.

How the amr shortcode any widget Fits In

Note that I am not going to enter the above shortcode directly into each post in the series. If I did that, I would still have to edit each series post when a new one is added to the series. Do not want to do that!

Instead, I’m going to add the nwbtoc shortcode into the Widgets for Shortcodes sidebar. Once saved, the amr shortcode any widget plugin will assign that new widget its own shortcode (see below).

Now I can enter that shortcode into each post in the series.

When a new post is added to the series, all I have to do is add that post’s ID to the list of IDs in the Widgets for Shortcodes widget, and the table of contents in every post in the series will be updated.

Closing Thoughts

If you know of a plugin that performs this function, I’d love to know about it. Also, I welcome your feedback on the method I’ve come up with.

Update: Plugins Found

Turns out ya gotta know the right search terms to use!

When I searced for “series post list”, I found these:

https://wordpress.org/plugins/organize-series/
https://wordpress.org/plugins/series/
https://wordpress.org/plugins/post-series-manager/
https://wordpress.org/plugins/really-simple-series/
https://wordpress.org/plugins/post-series/

Like what you see? Share with others and join my mailing list. No long-term commitment, unsubscribe any time.

Related Posts

  1. I Built a WordPress Plugin for Downloadable Files
  2. Dive Into WordPress Custom Post Types – Part 2
  3. Dive Into WordPress Custom Post Types – Part 3
  4. Display WordPress and WooCommerce Tags as Lists
  5. How to add an About Us blurb to every WordPress blog post

Reader Interactions

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Primary Sidebar

mailchimp signup

Subscribe to get notified when new articles are published. Unsubscribe any time. No spam. I promise. Check out my newsletter archives.

social

Twitter Facebook LinkedIn

Recent Articles

  • Custom MemberPress Pricing Pages December 19, 2025
  • CSS Data Attribute Override December 11, 2025
  • MemberPress Rules Using Custom Taxonomies and Custom Roles December 10, 2025
  • WP Staging Plugin: a First Look November 21, 2025
  • How to overlap elements with HTML and CSS (Grid) only August 13, 2025

Filter By Category/Tag

Categories

  • Case Studies (8)
  • For Staff (1)
  • General (72)
  • Portfolio (7)
  • Reviews (14)
  • Snippets (23)
  • Techniques (52)

Popular Tags

Advanced Custom Fields Blogging Child Themes Content Marketing CSS Customer Service Custom Fields Custom Post Types Diagnostics Domain Names Facebook FooGallery Genesis Hosting HTML Images iPhone Libra Live Chat Marketing Media MemberPress MemberPress Courses Membership Sites Mobile-Friendly MySQL Photo Gallery php Pinterest Plugins Post Formats Pricing Project Management SEBA SEO Seth Godin Shortcodes Social Networking Surveys Taxonomies Twitter Video Web design Web forms WordPress

Footer

Background

Web Sites | WordPress Support | Web Applications.

Formally trained in liberal arts and education (I have a B.A. in Government from Harvard and studied Secondary Education at Rutgers Graduate School), I have honed my skills in the communication arts and sciences as a teacher, trainer, instructional designer, writer, photographer, calligrapher, helpdesk manager, database programmer, and multimedia developer.

(I've also been a group counselor, waiter, bartender, bicycle messenger boy, computer salesman, carpenter's helper, financial analyst, and school board president.)

Tech

Systems since 1983.
Web sites since 1994.
PHP since 2001.
WordPress since 2007.

Contact

Book Meeting
770-772-5134
Email Jeff
Send Money
All Ways

Copyright 2026, nSiteful Web Builders, Inc.

Cookies Consent
To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
Functional Always active
The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
Preferences
The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
Statistics
The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
  • Manage options
  • Manage services
  • Manage {vendor_count} vendors
  • Read more about these purposes
View preferences
  • {title}
  • {title}
  • {title}
https://iframe.mediadelivery.net/embed/392008/42d18bc1-2adc-4741-b733-053d08d09c32
https://vz-000c5976-3ab.b-cdn.net/42d18bc1-2adc-4741-b733-053d08d09c32/play_720p.mp4

Receive occasional emails from Jeff