I was recently asked how I built the sitemap on Binary Moon so I thought I would share the code. The sitemap layout is actually one of the many custom page templates available in my WordPress theme, Elemental - however the code is very loosly based upon that in the original SRG Clean Archives plugin (before it was taken over by Geek With a Laptop).

Sitemaps are a single page that allows you to view every single post on a site. Perfect for Google to spider all of your content, and for users to quickly find old posts that they are looking for.
When making the sitemap I wanted to list all of the posts, and also to link to the monthly archives for each post - that way I would get maximum exposure for my sitemap - and it has a page rank of 6 (at the time of writing) so I must be doing something right.
The process is relatively simple:
- Grab all the months and years from the database
- Loop through the list of dates and grab the posts from each month, displaying them as you go
Easy right? The code, that you would add to your functions.php - would look something like the function below:
function bm_displayArchives() {
global $month, $wpdb, $wp_version;
// a mysql query to get the list of distinct years and months that posts have been created
$sql = 'SELECT
DISTINCT YEAR(post_date) AS year,
MONTH(post_date) AS month,
count(ID) as posts
FROM ' . $wpdb->posts . '
WHERE post_status="publish"
AND post_type="post"
AND post_password=""
GROUP BY YEAR(post_date),
MONTH(post_date)
ORDER BY post_date DESC';
// use get_results to do a query directly on the database
$archiveSummary = $wpdb->get_results($sql);
// if there are any posts
if ($archiveSummary) {
// loop through the posts
foreach ($archiveSummary as $date) {
// reset the query variable
unset ($bmWp);
// create a new query variable for the current month and year combination
$bmWp = new WP_Query('year=' . $date->year . '&monthnum=' . zeroise($date->month, 2) . '&posts_per_page=-1');
// if there are any posts for that month display them
if ($bmWp->have_posts()) {
// display the archives heading
$url = get_month_link($date->year, $date->month);
$text = $month[zeroise($date->month, 2)] . ' ' . $date->year;
echo get_archives_link($url, $text, '', '<h3>', '</h3>');
echo '<ul class="postspermonth">';
// display an unordered list of posts for the current month
while ($bmWp->have_posts()) {
$bmWp->the_post();
echo '<li><a href="' . get_permalink($bmWp->post) . '" title="' . wp_specialchars($text, 1) . '">' . wptexturize($bmWp->post->post_title) . '</a></li>';
}
echo '</ul>';
}
}
}
}Note that I am using the wp_query object (as detailed in my post "10 query_posts tips you probably don't know") throughout this example to stop the main query_posts instance from being ruined
To use the function above you would then need to create a custom page template (as detailed in the custom page template tutorial here). You can then call the function from within the new template.
23 Responses to “How to Build the Perfect WordPress Sitemap” Leave a reply ›
I use the Google Sitemap Generator plugin. Can this code still be implemented, or would that be redundant?
These are for two different things. The Sitemap Generator plugin is used to generate xml sitemaps whereas the code I used it for displaying html sitemap pages on your website.
BTW I changed your name to something resembling your real name
how can we call this into a page?
how to create page navigation for this sitemap?
not sure what you're looking for here? Could you give me some more info?
I meant how to create multiple pages for the sitemap, such as every "year" has its own page.
This is terrific. I also need to generate a Site Map where the Posts are listed by Category rather than date. Basically, I want to build a site map that reads like a Table of Contents for Posts ... where posts are listed alphabetically by title within their category, and reflecting the category hierarchy. Any ideas? Thanks!
This article feels a bit half-finished, unless I've missed something. Once the code is added to functions.php, how do you display the sitemap on a page?
Hi Joe - thanks for the feeback - I have added some extra notes to the bottom of the post to try to clarify what to do with the function.
Hi Ben,
Thanks for sharing this, I think your sitemap looks great. I've added the function to my functions.php and called it in my page temple. Unfortunately it's not outputting anything at all!
This is how I called the function...
Is there any reason that your code isn't working for me?
Thanks
and again!
echo $bm_displayArchives;
thanks for this post, but how to add a site map just contains pages not posts.
great tutorial and got it all working quite easily, however, unlike your sitemap on Binary Moon, this only outputs posts and not pages. Anyway to amend so that it generates page links in the sitemap?
I'm only just getting my head around WordPress but know a bit of PHP and SQL and have tried altering your SQL statement:
AND post_type="post"
to:
AND post_type="page"
however it still generates a map based on pages. Is it something to do with the_post() function?
thanks again though!
sorry that should say : it still generates a map based on posts rather than pages!
changing post to page should do the trick quite nicely. To be honest though - I would use the wp_list_pages command that will do this without any custom SQL commands.
And what about displaying posts and pages together? Is there an easy way to adapt your code to do that?
Thanks for this. This is the best approach I've come across and easy to use.
Hi Ben. Hopefully everything is good with you. I have paste the code given to my function.php but some of the script appear on top of my page header. Can you tell what I did wrong?
Hi Ben,
I followed your advice and got my "sitemap" up and running...
Just wanna say thxs
Grtz
awesome - glad I could help
Hello Ben,
I have an HTML based sitemap but it seems like Google don't like them much. May .xml based sitemap would be more appropriate. Any idea? Is there anyway I can create .xml sitemap without any PLUGIN? which won't need manual update? I do blog nearly everyday. So, manual .xml sitemap gonna be a real boring thing to do. Please help. Thanks.
My tutorial was for a public sitemap. If you want an automated system then the best thing to do is use a plugin - there's a couple of good ones out there so just google around
.
hello
I tried your code and it works nicely but it sticks with the posts and I would like it to list only my custom posts (livres).
So in the mysql query, i put AND post_type='livres'
but it keeps displaying regular posts instead of books !
Should I modify more the query ?
thank you