WordPress Sitemap Without A Plugin

WordPress sitemap without a plugin

When it comes to sitemaps, there is a variety of solutions with a ton of features and options out there for grabs. But anyone following my entries will have noticed, that I rather add a couple of lines of code to my functions.php than using another plugin. So I tried to create a simple way to implement a sitemap in my blog. Here is what I came up with:

The goal is a sitemap, where all entries would be orderd by category and dall static pages woul show up, too. Right, it’s easy to get a hold of the pages. But categories and posts outside of the Loop?

WordPress offers a variety of functions for that, but since we  just need the IDs and names/titles of the categories and posts, let’s work towards a better performance and get only the information needed and not all category- and post-objects.

We start with a new function in the functions.php file of our theme or in your functionality plugin. We need the global variable $wpdb, to execute the necessary database queries.

With the following SQL query we obtain the necessary information about the categories, limited to only the published posts, obviously.

function sitemap() {
    global $wpdb;
    $category_array = $wpdb->get_results("SELECT t.term_id, t.name FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = 'category' AND tt.count > 0");
    $sitemap = '<h3>'.__('Posts','domain').'</h3>' .
                '<ul class="categories">';

With a foreach-loop, we go through the objects and build the links to the category archive with the category IDs and names. Now we get all the posts assigned to the current category ID,  limited to the type ‚post’ and the status ‚published’.

foreach($category_array as $category){
        $sitemap .= '<li>'.__('Category: ', 'domain').'<a href="'.get_category_link($category->term_id).'" title="' . sprintf( __( "View all posts in %s" ), $category->name ) . '">'.$category->name.'</a><ul>';
        $post_array = $wpdb->get_results("SELECT p.ID, p.post_title FROM $wpdb->posts p INNER JOIN $wpdb->term_relationships r ON p.ID = r.object_id WHERE r.term_taxonomy_id = $category->term_id AND p.post_type = 'post' AND p.post_status = 'publish'");

With this data we build the next unordered list with all tiles and permalinks.
Lastly we take advantage of the popular wp_list_pages() function, where we exclude the page-ID of our sitemap,  as soon as it is established.  ‚Echo’ should be set to FALSE, otherwise the list pops up in unexpected places.

foreach($post_array as $post){
            $sitemap .= '<li><a href="'.get_permalink($post->ID).'" title="'.esc_attr($post->post_title).'">'.$post->post_title.'</a></li>';
        $sitemap .= '</ul>';
    $sitemap .= '</li></ul>';
    $sitemap .= '<h3>'.__('Pages','domain').'</h3><ul class="pages">';
    $sitemap .= wp_list_pages(array('echo'=>false, 'title_li'=>false, 'exclude'=>'343')).'</ul>';
    echo $sitemap;

Now, with the function finished, we create a new template, called Sitemap (or whatever you think is suited best). The markup should look somewhat like the page.php, though we paste the following lines in the content area:

<?php sitemap(); ?>

Next we create a new page in the amin menu and choose the sitemap template in the template dropown in the right column. After entering a title , we’re done.

Anyone who would like to know what the result looks like, simply goes to the Sitemap.
Have fun implementing it!


An alternative sitemap, using no custom queries is available at Sitemap: The WordPress Way.

Leave a Reply