Creating A WordPress Tag Index Page

For some reasons, I tend to stay away from tag clouds whenever possible. While they’re visually appealing, tag clouds tend to give focus on highly-used tags and it’s quite difficult to scan for certain topics that you might actually be interested in.

With that in mind, I wanted the users to:

  • See a list of all tags on my site.
  • See the tags sorted in alphabetical order to allow easy scanning.
  • Show number of frequency each tag has been used.
  • Provide a link for users to see posts related to the tag.

On this post, I’ll show you how you could achieve all the points above, while still keeping your tags visually appealing. In short, we’re going to create a page similar to the Tag Index page on octalforty.

Preparing the PHP file

First off, we’re going to create a new PHP file called tag-index.php and save it to your themes folder. Your tag-index.php should be on the same location as the widely-known functions.php. Once that’s done, we’ll include the code below to your tag-index.php:

<?php
/*
Template Name: Tag Index
*/

get_header(); ?>

    <div id="primary">
        <div id="content" role="main">
		
            <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
			
                <header class="entry-header">
                    <h1 class="entry-title"><?php the_title(); ?></h1>
                </header><!-- .entry-header -->

                <div class="entry-content">
                    <!-- Tag index code will be placed here -->
                </div><!-- .entry-content -->
				
                <footer class="entry-meta">
                    <!-- The footer for your tag index page -->
                </footer><!-- .entry-meta -->
			
            </article><!-- #post-<?php the_ID(); ?> -->
		
        </div><!-- #content -->
    </div><!-- #primary -->
		
<?php get_footer(); ?>

On line 2 – 4 on the above code, we’re telling WordPress the Template Name. This will be used when we’re going to create the actual page later on. The rest of the code is a copy of WordPress 2011 theme page markup. Feel free to make any modifications to suit your own theme.

Outputting the tags

Finally, the fun part.

On line 18 of your tag-index.php, replace that line with the code below:

<?php
    // Make an array from A to Z.
    $characters = range('a','z');
    // Check if $characters exists and ensure that it is an array.
    if( $characters && is_array( $characters ) ) {
        foreach( $characters as $index=>$character ) {
            // Get the tag information for each characters in the array.
            $tags = get_tags( array('name__like' => $character, 'order' => 'ASC') );
            // Output a wrapper so that our arrays will be contained in 4 columns.
            if ($index != 0 && $index % 4 == 0)  {
                $html = "<div class='post-tags clearfix' style='clear:left;'>";
            } else {
                $html = "<div class='post-tags clearfix'>";
            }
            // Output the character and use it as the title.
            $html .= "<h3 class='title'>{$character}</h3>";
            // Output the markup for each tag found for each character.
            if ($tags) {
                $html .= "<ul>";
                foreach ( (array) $tags as $tag ) {
                    $tag_link = get_tag_link($tag->term_id);
                    $html .= "<li class='tag-item'>";
                    if ( $tag->count > 1 ) {
                        $html .= "<p><a href='{$tag_link}' title='View all {$tag->count} articles with the tag of {$tag->name}' class='{$tag->slug}'>";
                    } else {
                        $html .= "<p><a href='{$tag_link}' title='View the article tagged {$tag->name}' class='{$tag->slug}'>";
                    }
                    $html .= "{$tag->name}</a><span>#{$tag->count}</span></p>";
                    $html .= "</li>";
                }
                $html .= '</ul>';
            }
            $html .= '</div>';
            // Output the markup for the current character.
            echo $html;
            // Increment the index by 1.
            $index++;
        }					
    }
?>

Easy huh? I’ve commented each line to ensure that it’s easier to understand what’s going around. If you’re unsure of something, just leave a comment eh?

Once you’re done figuring out what’s happening, save the file.

Create the page

Now go to your Add New Pages page on your WordPress admin. You should see a screen similar to the ones below:

Screenshot showing the Add New Page on WordPress.
Screenshot showing the Add New Page on WordPress.

Give your post a title (Hint: Tag Index). Under the Page Attributes section on the right of your screen, select Tag Index as the template.

Screenshot showing Tag Index set as the Template.
Screenshot showing Tag Index set as the Template.

Done? Awesome. Save and preview your page to see a list of tags ordered alphabetically. You can then style it according to your taste.


Comments

17 responses to “Creating A WordPress Tag Index Page”

  1. Hey! Nice one…

    Is there any way I can modify this to fetch tags from a particular category or custom post type?

    Thanks!

  2. @Siddharth Arun: Thanks πŸ™‚
    To get tags from a particular category (or categories), you could probably use this nifty function from WP forum.

    Hope that helps!

  3. Hi Yassir, thanks for the post, is there a way to get the related tags (by id or slug) to each tag as here: http://032c.com/topics/

    Please email me so i’ll explain better.

  4. Adriana Avatar
    Adriana

    Hi, I have a question πŸ™‚

    What if I want to hide the chars without tags?

    Thanks,

    A.

  5. @Adriana:

    Hey Adriana! Thanks for dropping by πŸ™‚

    To hide characters without tags, simply wrap the if ($tags) around the lines where you output the markup. Something like this :

    $tags = get_tags( array('name__like' => $character, 'order' => 'ASC') );
    if ($tags) {
    	if ($index != 0 && $index % 4 == 0)  {
    		$html = "<div class='post-tags clearfix' style='clear:left;'>";
    	} else {
    		$html = "<div class='post-tags clearfix'>";
    	}
    	$html .= "<h3 class='title'>{$character}</h3>";
    	$html .= "<ul>";
    	foreach ( (array) $tags as $tag ) {
    		$tag_link = get_tag_link($tag->term_id);
    		$html .= "<li class='tag-item'>";
    		if ( $tag->count > 1 ) {
    		$html .= "<p><a href='{$tag_link}' title='View all {$tag- rel="nofollow ugc">count} articles with the tag of {$tag->name}' class='{$tag->slug}'>";
    		} else {
    		$html .= "<p><a href='{$tag_link}' title='View the article tagged {$tag- rel="nofollow ugc">name}' class='{$tag->slug}'>";
    		}
    		$html .= "{$tag->name}</a><span>#{$tag->count}</span></p>";
    		$html .= "</li>";
    	}
    	$html .= '</ul>';
    	$html .= '</div>';
    }
    echo $html;
  6. this is awesome! i wonder if there is a way to get specific categories, rather than tags, to build a sort of multicolumn index of posts?

    any ideas?

    thx!

  7. Hi,

    I just want to show the list of all tags on the site. So I read you post and did this ->

    PHP START
    $tags = get_tags( array(‘order’ => ‘ASC’) );
    if ($tags) {
    $html .= “”;
    foreach ( (array) $tags as $tag ) {
    $tag_link = get_tag_link($tag->term_id);
    $html .= “”;
    $html .= “slug}’>”;
    $html .= “{$tag->name}
    “;
    $html .= “”;
    }
    $html .= ”;
    }
    PHP ENDS

    But it does not output anything. πŸ™

    Can you help, please.

  8. Thanks for the code but I was wondering if there was a way to get all the letters at the top of the page like..

    A B C D E F G….

    Such that when one clicks on a letter of the alphabet it would jump to the part of the list containing all tags starting with the said alphabet.

    So for instance if I open the tag-index page, right on the top I’d see the horizontal letter listing. When I click ‘G’ it would take me to the part of the page containing all tags starting with the letter ‘G’.

    Thank You!

  9. @Oge:

    Hi Oge, thanks for the comment!

    All you need to do is reuse the part where we loop the characters, and put it outside of the code instead. Probably like :

    <ul>
    <?php
    // #2 : Build a list of navigation from A to Z
       foreach (range('a', 'z') as $char) {
          $tagnav = "<li>";
          $tagnav .= "<a href='#tagnav-{$char}' class='tagnav-char' rel="nofollow ugc">{$char}</a>";
          $tagnav .= "</li>";
    		
       // Outputs the navigation
       echo $tagnav;
    	}
    ?>
    </ul>
    
    <?
    	// #1 : Build the list of tags, by using the code provided in the post
        // Make an array from A to Z.
        $characters = range('a','z');
        // Check if $characters exists and ensure that it is an array.
        if( $characters && is_array( $characters ) ) {
            foreach( $characters as $index=>$character ) {
                // Get the tag information for each characters in the array.
                $tags = get_tags( array('name__like' => $character, 'order' => 'ASC') );
                // Output a wrapper so that our arrays will be contained in 4 columns.
                if ($index != 0 && $index % 4 == 0)  {
                    $html = "<div class='post-tags clearfix' style='clear:left;'>";
                } else {
                    $html = "<div class='post-tags clearfix'>";
                }
                // Output the character and use it as the title.
                $html .= "<h3 id='tagnav-{$character}' class='title'>{$character}</h3>";
                // Output the markup for each tag found for each character.
                if ($tags) {
                    $html .= "<ul>";
                    foreach ( (array) $tags as $tag ) {
                        $tag_link = get_tag_link($tag->term_id);
                        $html .= "<li class='tag-item'>";
                        if ( $tag->count > 1 ) {
                            $html .= "<p><a href='{$tag_link}' title='View all {$tag- rel="nofollow ugc">count} articles with the tag of {$tag->name}' class='{$tag->slug}'>";
                        } else {
                            $html .= "<p><a href='{$tag_link}' title='View the article tagged {$tag- rel="nofollow ugc">name}' class='{$tag->slug}'>";
                        }
                        $html .= "{$tag->name}</a><span>#{$tag->count}</span></p>";
                        $html .= "</li>";
                    }
                    $html .= '</ul>';
                }
                $html .= '</div>';
                // Output the markup for the current character.
                echo $html;
                // Increment the index by 1.
                $index++;
            }                    
        }	
    ?>

    Hope that helps!

  10. thanks! One little problem though, that seems to make the letters go vertically instead of horizontally. Check it out at http://www.nollywoodreinvented.com/all-actors, any help will be appreciated

  11. Hello,

    i want to ask how can i display the tags not in A to Z?

    i.e. :

    #1 Hit Songs Cover Band
    !!!
    β€œWeird Al” Yankovic

    or some other words from different languages.

    Thank you very much! great job !

  12. Tks for you post. Such that when one clicks on a letter of the alphabet it would jump to the part of the list containing all tags starting with the said alphabet. Plz keep update it!

  13. @Tai game kim cuong: Thanks for dropping by!

    Did you see my answer to Oge’s comment above?

  14. @alex: Thanks for stopping by Alex!

    On top of my mind, you should be able to sort it the tags based on another array, which you maintain manually. A bit of a hassle, but it would give you the flexibility that you need.

    Example:

    array('#', '!');

    Regarding characters from other languages, you could probably make use of SORT_LOCALE_STRING but sadly, I haven’t had a chance to personally play around with it.

    Do share with me if you’ve managed to solve it and share it here πŸ™‚

  15. @Yassir Yahya: Hi, thanks for your reply.

    but the point is when i select the array, all the tags show.

    i dont know why…

  16. testing Avatar
    testing

    I had the same problem with umlauts (language) and special characters. I noticed that ‘Γ€’ is correctly treated as ‘a’ but `ß` for example never appeared. So I used this approach:

    setlocale(LC_ALL, ‘de_DE@euro’, ‘de_DE’, ‘de’, ‘ge’);
    // get all tags
    $my_tags = get_tags( array(‘order’ => ‘ASC’) );
    $tag_array = array();
    foreach($my_tags as $tag){
    $tag_array[] = $tag->name;
    }

    function firstCharArray($array){
    $result = array();
    foreach($array as $item){
    $result[] = strtoupper(mb_substr($item, 0, 1, “utf-8”));
    }

    return array_unique($result);
    }

    // get first characters to build our array
    $characters = firstCharArray($tag_array);

    // Build a list of navigation from A to Z
    foreach ($characters as $char) {
    $tagnav .= “{$char} “;
    }
    // Outputs the navigation
    echo $tagnav . ”;

    Here I extract the first characters of the tags and I build the list as above mentioned (including navigation). Don’t know how it works for special characters but I’ll let it with this solution.

  17. […] stumbled upon Yassir Yahya’s tutorial and quickly implemented it. Problem is, when WordPress 3.7 was released, they changed the way the […]