A Simple, Custom XML Sitemap Generator for WordPress

August 16, 2016

The good WordPress plugins for XML sitemaps don’t produce static sitemap files. This is the PHP script I use, which I consider better for my purposes. It creates a static sitemap file that doesn’t include any of the taxonomy archive pages (categories, tags, date-based, etc.). My website doesn’t use any of those pages and even if it did, only the regular posts and pages are important.

My script only supports permalinks set with “/%postname%/”. You’ll have to change it support a different format.

The Sitemap Script through WordPress

There are two ways to run this script. One is by using WordPress functions and the other is by using Cron. I prefer Cron and I run it once an hour. I doubt Google retrieves the sitemap more than once a day but I don’t know what part of the day that is.

These are the WordPress functions to use if you want the sitemap generated every time you add, edit or remove a post (you obviously have to edit the “include” line for both):

function sitemap_update($new_status, $old_status, $post) {
  if ($new_status != $old_status) {
    include '/path-to-script/script.php';
add_action('transition_post_status', 'sitemap_update', 10, 3);
function sitemap_edit($post_ID, $post) {
  if ($post->post_status == 'publish') {
    include '/path-to-script/script.php';
add_action('edit_post', 'sitemap_edit', 10, 2);

This is the script to go with them:

$today = date( 'Y-m-d' );
$site_path = get_home_path();
$sitemap_filename = $site_path . '/sitemap.xml';
$site_url = home_url( '/' );
$results = get_posts( array('numberposts' => -1, 'orderby' => 'modified', 'post_type' => array( 'post','page' ) ) );
$sitemap = '<?xml version="1.0" encoding="UTF-8"?>' . "n" .
           '<urlset xmlns="">' . "n" .
           "t<url>n" .
           "tt<loc>$site_url</loc>n" .
           "tt<lastmod>$today</lastmod>n" .
           "tt<changefreq>monthly</changefreq>n" .
foreach ($results as $post) {
  $filename = $post->post_name;
  if ( strstr( $filename, '?' ) ) continue; // an odd quirk I discovered
  $a = explode( ' ', $post->post_modified );
  $postdate = $a[0];
  $sitemap .= "t" . '<url>' . "n" .
              "tt<loc>$site_url$filename/</loc>n" .
              "tt<lastmod>$postdate</lastmod>n" .
              "tt<changefreq>daily</changefreq>n" .
$sitemap .= '</urlset>' . "n";
file_put_contents( $sitemap_filename );

The Sitemap Script through Cron

I put all the PHP scripts I run from Cron in the directory above the WordPress root directory. That directory isn’t publicly accessible. Two changes must be made to the above script to run it from Cron. The first change is to replace the first two lines (not counting the PHP opening tag) with:

date_default_timezone_set( 'Asia/Manila' ); // your timezone not mine
$today = date( 'Y-m-d' );
$site_path = __DIR__ . '/document-root';    // change "document-root" to the WordPress root directory name
include $site_path . '/wp-load.php';

The second change is to insert these lines at the bottom (before the PHP closing tag):

chmod ( $sitemap_filename, 0644 );
chgrp( 'www-data' );
chown( 'www-data' );

According to, you can have up to 50,000 URLs in a single sitemap file. Since I only put posts and pages (no taxonomies) in my sitemap file, I’ll never reach 50,000 URLs. Not in this lifetime, anyway.

Please go to this alternate page if you would like read or post comments.


Categories: Technology

Tags: , , ,

Previous and Next Articles (if any):

« »


Please read some of my more important pages if you have the time:

Comments Policy           Privacy Policy

RTCXpression established Feb 28, 2011
Copyright © 2013-2017 RT Cunningham
Hosted at Digital Ocean