WordPress Sitemap Without Plugins

Another WordPress Tutorial, this time I will take you through creating a custom WordPress sitemap without plugin.

Create a WordPress sitemap without plugins

Tired of plugin bloat? Well there is a simple way to create a custom WP sitemap without using any plugins

This is a super simple and quick guide to help you create a WordPress Sitemap without using a plugin. No plugin required at all! Ok, below is the code snippet you'll need and a quick guide.

Updates for 2022

Based on some feedback I have updated the sitemap page to include: 1. Separate loops for one Custom Post Type and a separate loop for multiple Custom Post Types 2. The ability to exclude certain posts, pages, custom post type posts, woocommerce products 3. Increase readability by increasing spacing and clearer annotations/comments

Updates for 2021

As this is one of the most popular tuts on my blog (thanks for visiting), I have updated this WordPress Sitemap without a plugin for 2022. This includes more annotation, custom post types, and an improved WP Query loop. 1. Custom Post Types: I’ve included CPTs on this sitemap page, so all you need to do is replace the cpt-slug in the WP Query with your CPTs slug 2. Improved WP Query Loop: I’ve added a few extra options on all the WP Query loops below. That includes ordering by alphabetically by title 3. More Annotation: I’ve added some more annotation to make it easier for you to understand and customise the loop below

Why would you want to not use any third-party plugins to create a sitemap?

It’s really simple. All WordPress websites created by the average user should look to maintain a fully functioning site with somewhere around ~10 front-facing plugins. For reasons such as speed, flexibility, security and compatibility. Some plugins which are not secure can leave your website vulnerable, they can also be incompatible with other plugins resulting in your website not loading and producing errors, and the third reason because of speed, some plugins are bulky and overloaded with code. Oh, and most important of all it is actually super simple to do if you follow these easy instructions below. So, pull up your sleeves you’ve got to get stuck in and learn how to create a WordPress Sitemap without using a plugin.

Create WordPress sitemap without plugin

Before you start – You need to have administrative access to your WordPress site and FTP access. You should also always take a full database and theme file backup before making any changes. 1. Go to your theme folder 2. Create and name a file page-sitemap.php 3. Paste the code below into the page-sitemap.php file 4. Create a new page in the backend of your WordPress install. Select the page template “Sitemap” 5. Now tweak to fit your site

WordPress Sitemap Page Code

Below is the WordPress sitemap file. This supports Posts, Pages, Custom Post Types and WooCommerce Products. If you don’t want or need Custom Post Types or WooCommerce products support then just delete those loop at the bottom (I’ve annotated each section so should be easy to find).

<?php /* Template Name: Sitemap */ get_header(); ?>
<section id="sitemap"> <div class="sitemap-heading"> <h1>Sitemap</h1> </div> <!-- START WordPress Posts Loop --> <div class="sitemap-posts"> <h2>Posts</h2> <ul> <?php $wp_posts = new WP_Query( array( 'post_type' => 'post', // slug for posts 'posts_per_page' => -1, // -1 shows all posts 'post_status' => 'publish', // only shows published posts 'post__not_in' => array( 1, 2, 3 ) // Enter post ids here to exclude posts 'orderby' => 'title', // orders by post title 'order' => 'ASC' // orders post title alphabetically ) ); ?> <?php while ( $wp_posts->have_posts() ) : $wp_posts->the_post(); ?> <li> <a href="<?php echo get_permalink(get_the_ID()); ?>" rel="dofollow" title="<?php the_title(); ?>"> <?php the_title(); ?> </a> </li> <?php endwhile; wp_reset_query(); ?> </ul> </div> <!-- END WordPress Posts Loop --> <!-- START WordPress Pages Loop --> <div class="sitemap-pages"> <h2>Pages</h2> <ul> <?php $wp_pages = new WP_Query( array( 'post_type' => 'page', // slug for pages 'posts_per_page' => -1, // -1 shows all pages 'post_status' => 'publish', // only shows published pages 'post__not_in' => array( 1, 2, 3 ) // Enter post ids here to exclude pages 'orderby' => 'title', // orders by page title 'order' => 'ASC' // orders page title alphabetically ) ); ?> <?php while ( $wp_pages->have_posts() ) : $wp_pages->the_post(); ?> <li> <a href="<?php echo get_permalink(get_the_ID()); ?>" rel="dofollow" title="<?php the_title(); ?>"> <?php the_title(); ?> </a> </li> <?php endwhile; wp_reset_query(); ?> </ul> </div> <!-- END WordPress Pages Loop --> <!-- START WordPress Custom Post Type Loop - Delete this section if you are not using Custom Post Types --> <div class="sitemap-custom-post-types"> <h2>Custom Post Type</h2> <ul> <?php $wp_cpt = new WP_Query( array( 'post_type' => 'cpt-slug', // Change this to the slug of your Custom Post Type (cpt) 'posts_per_page' => -1, // -1 shows all cpt posts 'post_status' => 'publish', // only shows published cpt pages 'post__not_in' => array( 1, 2, 3 ) // Enter post ids here to exclude custom posts 'orderby' => 'title', // orders by cpt post title 'order' => 'ASC' // orders cpt posts title alphabetically ) ); ?> <?php while ( $wp_cpt->have_posts() ) : $wp_cpt->the_post(); ?> <li> <a href="<?php echo get_permalink(get_the_ID()); ?>" rel="dofollow" title="<?php the_title(); ?>"> <?php the_title(); ?> </a> </li> <?php endwhile; wp_reset_query(); ?> </ul> </div> <!-- END WordPress Custom Post Type Loop - Delete this section if you are not using Custom Post Types --> <!-- START WordPress Multiple Custom Post Type Loop - Delete this section if you are not using Custom Post Types --> <div class="sitemap-custom-post-types"> <h2>Multiple Custom Post Types</h2> <ul> <?php $wp_multiple_cpts = new WP_Query( array( 'post_type' => array('cpt-slug-1', 'cpt-slug-2', 'cpt-slug-3'), // Change this to the slug of your Custom Post Type (cpt) 'posts_per_page' => -1, // -1 shows all cpt posts 'post_status' => 'publish', // only shows published cpt pages 'post__not_in' => array( 1, 2, 3 ) // Enter post ids here to exclude custom posts 'orderby' => 'title', // orders by cpt post title 'order' => 'ASC' // orders cpt posts title alphabetically ) ); ?> <?php while ( $wp_multiple_cpts->have_posts() ) : $wp_multiple_cpts->the_post(); ?> <li> <a href="<?php echo get_permalink(get_the_ID()); ?>" rel="dofollow" title="<?php the_title(); ?>"> <?php the_title(); ?> </a> </li> <?php endwhile; wp_reset_query(); ?> </ul> </div> <!-- END WordPress Multiple Custom Post Type Loop - Delete this section if you are not using Custom Post Types --> <!-- START WooCommerce Products Loop - Delete this section if you are not using WooCommerce --> <div class="sitemap-woocommerce-products"> <h2>Products</h2> <ul> <?php $woo_products = new WP_Query( array( 'post_type' => 'product', // slug of woocommerce products 'posts_per_page' => -1, // -1 shows all products 'post_status' => 'publish', // only shows published products 'post__not_in' => array( 1, 2, 3 ) // Enter post ids here to exclude products 'orderby' => 'title', // orders by product title 'order' => 'ASC' // orders product title alphabetically ) ); ?> <?php while ( $woo_products->have_posts() ) : $woo_products->the_post(); ?> <li> <a href="<?php echo get_permalink(get_the_ID()); ?>" rel="dofollow" title="<?php the_title(); ?>"> <?php the_title(); ?> </a> </li> <?php endwhile; wp_reset_query(); ?> </ul> </div> <!-- END WooCommerce Products Loop - Delete this section if you are not using WooCommerce -->
</section>
<?php get_footer(); ?>

Quickfire FAQs