How to create HTML sitemap on WordPress without plugin

In this tutorial I will show you how to create HTML sitemap in WordPress without using plugin. There are a lot of HTML sitemap plugins for WordPress out there, but this article focuses on to how to generate sitemap without one.

While using a plugin would be an easy way to add a HTML sitemap, there are reasons to do it manually. Site speed is one of those, but I really like to get my hands dirty and create a sitemap page that I can customize however I want. Hopefully you will find this tutorial useful and after you read trough it, be able to create HTML sitemap to help your users navigate better.

Why create HTML sitemap for users

A sitemap is a page on the website that links to important content. It doesn’t have to link to every single page or post on your website, but sitemaps help your visitors explore your website. HTML sitemap for users is different than the XML Sitemap for search engines but it still has SEO benefits. If you don’t believe me, check out what Matt Cutts has to say on the subject.

Create WordPress HTML sitemap without plugin step by step

Ok so let’s get started. I followed this tutorial by Yoast. These guys are SEO experts so it makes sense to listen what they have to say on the topic. However, their code didn’t really work 100% on this blog, so I had to make a lot of changes. Maybe it was just a theme related issue, but if that code doesn’t work properly for you too, feel free to follow my tutorial below.

Step 1: Creating WP theme partial

Create a partials folder within your (child) theme folder. To do this you can use an FTP client or cPanel interface. Navigate to your active theme folder and create new folder inside. Give it a name of partials. This is where you can keep your template parts including this one for the HTML sitemap page. Inside of partials folder, create new file. Name it sitemap.php

Step 2: Creating sitemap.php code

Copy and paste the following code in your sitemap.php file

'exclude_admin' => false,
// Add pages you'd like to exclude in the exclude here
'exclude' => '', // enter the ID or comma-separated list of page IDs to exclude
'title_li' => '',
// Add categories you'd like to exclude in the exclude here
$learnedia_cats = get_categories('exclude=');
foreach ($learnedia_cats as $learnedia_cat) {
$learnedia_posts_by_slug = array(
'category_name'    => $learnedia_cat->slug,
'exclude'          => '', // enter the ID or comma-separated list of page IDs to exclude
'numberposts'      => '10' // number of posts to show, default value is 5
$learnedia_posts_array = get_posts( $learnedia_posts_by_slug );
echo "<li><h3>".$learnedia_cat->cat_name."</h3>";
echo "<ul>";
foreach ($learnedia_posts_array as $learnedia_post){
echo '<li><a href="'.get_permalink($learnedia_post).'">'.get_the_title($learnedia_post).'</a></li>';
echo "</ul>";
echo "</li>";

I’ve used here the code provided by Yoast for listing authors and author posts as well as the page listing. I did not need these lines on my blog, so I deleted it. It might make sense for you to list authors and pages so you can keep that. If you don’t want to list all of the authors or/and all of the pages, you can exclude them by slug within respective arrays.

Code which lists the posts is where the fun starts. As opposed to Yoast, I used the get_posts function to retrieve all of the posts within a specific category. Foreach loop goes through the categories. In each iteration, posts are called that correspond to the category using $learnedia_cat->slug. Another foreach loop goes through array of posts and each post title is printed within an li element with a corresponding link to the full post.

Step 3: Calling sitemap template part

To call a sitemap template part use the following code:

<?php get_template_part('/partials/sitemap'); ?>

If you are interested to know how get_template_part function works, you can consult the WordPress Code Reference here or read this helpful post.
You can call this template part within a special designed page template.

Creating HTML Sitemap WordPress Page Template

You can create a sitemap WordPress page template by duplicating your page.php file. This is very useful because you can create a page called Sitemap and give it a Sitemap template.

Step 1: Rename the copied page.php file to page-sitemap.php. Open it, and below the call to the_content(); add this code

<?php get_template_part('/partials/sitemap'); ?>

Step 2: Now use code editor and open the page-sitemap.php file. After the opening php tag, add this comment

Template Name: Sitemap Page

This will make your sitemap page template listed within Page Attributes box in page editor.

Step 3: Use the Sitemap template
You can find it in the Template dropdown. When you create your Sitemap page, just select it from the drop-down and your Sitemap page will automatically display whatever you chose in the sitemap.php file.
You can use this sitemap template for whatever WordPress page you want and there is the beauty of this approach.

However, maybe you don’t need this special template for sitemap. Or your theme does not have the_content(); function within page.php (it could be placed in another template part). In any case, there is another neat trick you can use to display your HTML sitemap template part on just the Sitemap page.

Displaying HTML sitemap template part without a custom Sitemap page template

To display HTML sitemap template part on just one page that you created for adding the WordPress HTML sitemap, you can use the is_page function. Follow the steps below

Step 1. Create a Sitemap page
Create a new page and give it a name. It makes sense to give it a name of Sitemap. Plain and simple. In this case, page slug will be sitemap.

Step 2. Use the slug to identify the sitemap page
Use the sitemap within the is_page function. Paste the following code under the_content() function in your template or template part which contains it.

<?php if(is_page('sitemap')){ get_template_part('partials/sitemap');} ?>

This code checks if the current page is a page with the sitemap slug. If the statement is true, get_template_part(‘partials/sitemap’); will be called. If false, nothing happens. That is it.

Hope you find this article useful. If so, please share on social media. Also if you have something to add to the code I provided within this HTML sitemap in Worpdpress tutorial without plugin, please do comment below.

11 thoughts on “How to create HTML sitemap on WordPress without plugin”

  1. Thanks for the great article .
    I read yaost article and then come to this newer version . I follow the instructions but my sitemap page is blank
    Do you have any Idea what would goes wrong ? I even see the sitemap page template listed within Page Attributes box in page editor. but the page I created is blank .

    Also It would be great if you could expand the code to list woocommerce products categories and products attrebutes along with products tags .
    thanks again

  2. thank you for the reply ,
    I enabled the debug mod and found that there is already <? php tag before the_content(); so I should remove them from the code in this article . if this is for every theme so the php tag should be removed from the code in article . thanks

    Regarding woocommerce html sitemap , recently woocommerce add [product_categories] so show the products category but this will show the category along with a thumbnail wich is not good for html site map . could you expand the code to list woocommerce products categories , products attributes and products tags .

    Thanks again for great article .

    • Hi Mo, I updated the code snippet in the article with a comments on how to exclude page(s) and post(s). You need to find a page or post ID which you want to exclude, you can do that when you’re editing post/page – you will see the ID in the URL when you or on the editing screen in WP dashboard. I also added ‘numberposts’ as an argument in get_posts function that pulls more than default of 5 posts. As for your WooCommerce question, that is a good idea to look into, I might do that later on if I find some time. Cheers

  3. Thank you so much ,
    Yes , I just found out it should be comma seprated page ids .
    Regarding product category , I found this code but it is not listed properly , again I do not know how to exclude some categories . I hope this will save you some time .

    ‘product_cat’ );
    $terms = get_terms(‘product_cat’, $args);

    if (count($terms) > 0) {
    echo ”;
    foreach ($terms as $term) {
    echo ‘slug . ‘” title=”‘ . sprintf(__(‘View all post filed under %s’, ‘my_localization_domain’), $term->name) . ‘”>’ . $term->name . ‘‘;
    echo ”;

    I will let you know if I found codes regarding products tags and attributes .

  4. this works fine :

    ‘orderby’ => $orderby,
    ‘order’ => $order,
    ‘hide_empty’ => $hide_empty,
    ‘include’ => $ids
    $product_categories = get_terms( ‘product_cat’, $args );
    $count = count($product_categories);
    if ( $count > 0 ){

    foreach ( $product_categories as $product_category ) {
    echo “”;
    echo ‘‘ . $product_category->name . ‘‘;
    echo “”;



Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.