How To Add a Dynamic HTML Sitemap in WordPress Without a Plugin

In this tutorial, I will show you how to dynamically display an HTML sitemap for your WordPress blog without the need of a plugin. Dynamically means that the sitemap updates automatically with every new post and other blog changes. Yes, there are plugins that add an HTML sitemap to your blog. But I encourage you to read my previous post about unnecessarily adding plugins to your theme. Also in many cases, you add specific things to your sitemap that are not supported in a plugin. You really don´t need a plugin for such a simple task.

What is an HTML sitemap?

An HTML sitemap provides a mechanism to display the blog´s structure, the list of posts and pages, and other sections, so that users will get a quick overview of the content. An HTML sitemap primarily focus on helping your users easily navigate your blog.

Some WordPress themes natively support a sitemap template file. In this case, you if your WordPress theme already has a built-in sitemap page template, then all you have to do is create a new page in your WordPress dashboard, choose the sitemap page template, and then click Publish. And you´re done!

Why should you Use a sitemap Page?

Most bloggers don´t have a sitemap page and this is a mistake. An HTML sitemap is designed for your visitors.

An HTML sitemap acts as a directory that helps your users find their way around. It shows all your pages, posts, archives, categories and authors in one convenient location.

An HTML sitemap improves the navigation of your blog, where visitors can quickly find a specific post and get a quick overview about the blog´s content.

An HTML sitemap not only help your visitors find more information but also keep them on your blog longer.

An HTML sitemap is user-friendly, enhances the user experience and Web usability.

Demo of the HTML sitemap for this Blog | Final Result

To see how the sitemap page looks like, after implementing the code below, check out the HTML sitemap of this blog.

Features of My “HTML sitemap” Code

The code has the following features:

  1. Displays the list of Authors with the number of posts per author. An author with no posts will not be listed.
  2. Displays the list of Pages. You have the option to exclude pages as you wish.
  3. Displays the list of Posts. Posts, along with the post date and number of comments per post, are listed under their respective categories.
  4. Displays a post once, even if it listed in multiple categories (or subcategories).
  5. You have the option to Exclude categories (or subcategories).
  6. An empty category will not be listed.
  7. Displays the list of Monthly Archives.
  8. The code is tested to work properly with all major browsers.
  9. The code is tested to work properly with WordPress but it will work with earlier versions.
  10. The code is XHTML valid.
  11. The code is dynamic, the sitemap page automatically updates with any new changes to the blog.
  12. However; the code does NOT support Custom Post types.

Dynamic HTML sitemap Code | How To Create your sitemap Page

Here are the 5 steps required to create a dynamic HTML sitemap for your WordPress blog:

Step 1. Locate to your WordPress theme folder and make a copy of the page.php file, rename the new file to page-sitemap.php

Step 2. Open page-sitemap.php with your preferred editor or in the WordPress dashboard.

Step 3. Add the following code (CODE-1) to the top of page-sitemap.php file:

CODE-1:

<?php
/*
Template Name: HTML Sitemap Page
*/
?>

Step 4. Replace the_content(); tag and the code around it as necessary with the following code (CODE-2):

CODE-2:

<div class="html-sitemap">
    <h2>Author(s):</h2>
    <ul class="sitemap-authors">
    <?php 
       //http://codex.wordpress.org/Function_Reference/wp_list_authors
       wp_list_authors('exclude_admin=1&optioncount=1');
    ?>
    </ul>
         
    <h2>Pages:</h2>
    <ul class="sitemap-pages">
    <?php
      //http://codex.wordpress.org/Function_Reference/wp_list_pages
      wp_list_pages('exclude=889&title_li='); //***Exclude page Id, separated by comma. I excluded the sitemap of this blog (page_ID=889).
    ?>
    </ul> 
      
    <h2>Posts:</h2>
    <ul>
    <?php
    //http://codex.wordpress.org/Function_Reference/get_categories
    $cats = get_categories('exclude='); //***Exclude categories by ID, separated by comma if you like.
     
    foreach ($cats as $cat) {
      echo '<li class="category">'."\n".'<h3><span class="grey">Category: </span>'.$cat->cat_name.'</h3>'."\n";
      echo '<ul class="cat-posts">'."\n";
       
      //http://codex.wordpress.org/Function_Reference/query_posts
      query_posts('posts_per_page=-1&cat='.$cat->cat_ID); //-1 shows all posts per category. 1 to show most recent post.
         
      //http://us3.php.net/while ; http://codex.wordpress.org/The_Loop ; http://codex.wordpress.org/The_Loop_in_Action
      //http://codex.wordpress.org/Function_Reference/the_time ;  http://codex.wordpress.org/Function_Reference/the_permalink 
      //http://codex.wordpress.org/Function_Reference/the_title ; http://codex.wordpress.org/Function_Reference/comments_number
      while(have_posts()): the_post(); 
         //http://codex.wordpress.org/Function_Reference/get_the_category
         $category = get_the_category();
         //Display a post once, even if it is in multiple categories/subcategories. Lists the post in the first Category displayed.
         if ($category[0]->cat_ID == $cat->cat_ID) {?>
            <li><?php the_time('M d, Y')?> &raquo; <a href="<?php the_permalink() ?>"  title="Permanent Link to: <?php the_title(); ?>">
            <?php the_title(); ?></a> (<?php comments_number('0', '1', '%'); ?>)</li>
       <?php } //endif
        endwhile; //endwhile
       ?>
      </ul> 
      </li>
    <?php } ?>
    </ul>
    <?php 
    //http://codex.wordpress.org/Function_Reference/wp_reset_query
    wp_reset_query(); 
    ?>   
    <h2>Archives:</h2>   
    <ul class="sitemap-archives">   
    <?php 
      //http://codex.wordpress.org/Function_Reference/wp_get_archives
      wp_get_archives('type=monthly&show_post_count=true'); 
    ?>   
    </ul>     
</div>

CODE-2 Notes:

The idea of choosing page.php is to preserve your blog´s layout (header, sidebar, footer) and style. In other themes, other files might be a better starting point. It all depends on your theme.

For instance, for the Clear Line theme, I started with the right_sidebar.php file as a basis (since my blog has a right sidebar only).

On line 23 of the code, I excluded the sitemap page of this blog from showing up in the “Pages:” list. Of course, your HTML Sitemap Page ID is different. If you don´t know how to find the page ID, read my previous tutorial on How To Find the Page ID.

CODE-2 was tested to work on WordPress 3.0 and above. But I hope that you will upgrade to the latest WordPress version.

You can customize the code to fit your blog!

Code References:

wp_get_archives() ; the_time() ; the_permalink() ; the_title() ; comments_number() ; get_the_category() ; while – PHP Manual ; The Loop ; The Loop in Action ; query_posts() ; wp_list_authors() ; wp_list_pages()wp_reset_query()

Step 5. Login to your WordPress dashboard. In your Administration Screens, and on the Left Panel, go to Pages -> Add new. This will create a new page as shown in the image below:

In the Page Attributes box, choose the HTML Sitemap Page template and then click Publish. And that´s it!

Real Example | Where to Add the HTML SiteMap Code

To give you a real example. One of the themes I am using for this blog is the Emplode theme. Below is the original code of the page.php file.

Original page.php file | Emplode Theme

<?php get_header(); ?>
 
    <?php if (have_posts()) : ?>
        <?php while (have_posts()) : the_post(); ?>
        <div class="post" id="post-<?php the_ID(); ?>">
            <div class="post_title"><h2><?php the_title(); ?></h2></div>
            <?php edit_post_link('Edit this page', '<div class="post_date">', '</div>'); ?>
             
            <div class="post_body">
                <?php the_content('<p class="serif">Read the rest of this page &raquo;</p>'); ?>
 
                <div class="clearer">&nbsp;</div>
            </div>
 
            <?php wp_link_pages(array('before' => '<div class="post_meta archive_pagination"><strong>Pages:</strong> ', 'after' => '</div>', 'next_or_number' => 'number')); ?>
 
        </div>        
        <?php endwhile; ?>
 
    <?php else : ?>
        <h2>Not Found</h2>
        <p>Sorry, but you are looking for something that isn't here.</p>
        <?php get_search_form(); ?>
 
    <?php endif; ?>   
 
<?php get_sidebar(); ?>
<?php get_footer(); ?>

Now, to create the HTML sitemap page for this blog. First, I made a copy of the page.php file, and renamed page-sitemap.php. Second, I added (CODE-1 and CODE-2) to the page-sitemap.php file. Notice that: CODE-1 is added at the top of the file, and the get_header()), get_sidebar() and get_footer() tags are preserved and also the page layout is preserved.

Below is the source code of the page-sitemap.php file for the Emplode Theme that I used for this blog.

page-sitemap.php file | Emplode Theme

<?php
/*
 Template Name: HTML Sitemap Page
*/
?>
<?php get_header(); ?>
 
<div class="post_body"> 
<div class="html-sitemap">
    <h2>Author(s):</h2>
    <ul class="sitemap-authors">
    <?php 
       //http://codex.wordpress.org/Function_Reference/wp_list_authors
       wp_list_authors('exclude_admin=1&optioncount=1');
    ?>
    </ul>
      
    <h2>Pages:</h2>
    <ul class="sitemap-pages">
    <?php
      //http://codex.wordpress.org/Function_Reference/wp_list_pages
      wp_list_pages('exclude=889&title_li='); //***Exclude page Id, separated by comma. I excluded the sitemap of this blog (page_ID=889).
    ?>
    </ul>  
    <h2>Posts:</h2>
    <ul>
    <?php
    //http://codex.wordpress.org/Function_Reference/get_categories
    $cats = get_categories('exclude='); //***Exclude categories by ID, separated by comma if you like.
     
    foreach ($cats as $cat) {
      echo '<li class="category">'."\n".'<h3><span class="grey">Category: </span>'.$cat->cat_name.'</h3>'."\n";
      echo '<ul class="cat-posts">'."\n";
       
      //http://codex.wordpress.org/Function_Reference/query_posts
      query_posts('posts_per_page=-1&cat='.$cat->cat_ID); //-1 shows all posts per category. 1 to show most recent post.
         
      //http://us3.php.net/while ; http://codex.wordpress.org/The_Loop ; http://codex.wordpress.org/The_Loop_in_Action
      //http://codex.wordpress.org/Function_Reference/the_time ;  http://codex.wordpress.org/Function_Reference/the_permalink 
      //http://codex.wordpress.org/Function_Reference/the_title ; http://codex.wordpress.org/Function_Reference/comments_number
      while(have_posts()): the_post(); 
         //http://codex.wordpress.org/Function_Reference/get_the_category
         $category = get_the_category();
         //Display a post once, even if it is in multiple categories/subcategories. Lists the post in the first Category displayed.
         if ($category[0]->cat_ID == $cat->cat_ID) {?>
            <li><?php the_time('M d, Y')?> &raquo; <a href="<?php the_permalink() ?>"  title="Permanent Link to: <?php the_title(); ?>">
            <?php the_title(); ?></a> (<?php comments_number('0', '1', '%'); ?>)</li>
       <?php } //endif
        endwhile; //endwhile
       ?>
      </ul> 
      </li>
    <?php } ?>
    </ul>
    <?php 
    //http://codex.wordpress.org/Function_Reference/wp_reset_query
    wp_reset_query(); 
    ?>
     
    <h2>Archives:</h2>   
    <ul class="sitemap-archives">   
    <?php 
      //http://codex.wordpress.org/Function_Reference/wp_get_archives
      wp_get_archives('type=monthly&show_post_count=true'); 
    ?>   
    </ul>     
</div>
</div>
   
<?php get_sidebar(); ?>
<?php get_footer(); ?>

Notice that I not only replaced the the_content() tag but I also removed the loop. The point to keep in mind is that you need to keep the header, sidebar and footer tags and also preserve the page look as your blog´s.

Styling the HTML sitemap | style.css

Finally we need to style the HTML Sitemap Page with CSS. The following code is what I used for this blog. The code should be added to your theme´s CSS file (called style.css). Change it to fit your blog´s design.

.html-sitemap h2{
padding-top: 10px;
}
.category {
list-style:none;
padding-bottom: 5px;
}
.grey {
color: #777;
background-color: inherit;
}
.cat-posts {
padding-bottom: 10px;
padding-top: 10px;  
}
.cat-posts li{
padding-bottom: 5px;
list-style:square;  
}
.sitemap-authors li, .sitemap-pages li, .sitemap-archives li{
padding-bottom: 5px;
}

Your Turn to Talk

You now have the choice to Create an Effective HTML sitemap Page for your WordPress Blog and customize it to fit your blog´s theme, without the need of a plugin.

How easy did you find this tutorial to implement? Do you have a hard time integrating the code into your WordPress theme? Do you have something to add or anything else to say?

Categories: