Menu

RTCXpression

Close

A Simple, Custom XML Sitemap Generator for WordPress

- August 16, 2016

sitemap 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:

<?php
$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="http://www.sitemaps.org/schemas/sitemap/0.9">' . "n" .
           "t<url>n" .
           "tt<loc>$site_url</loc>n" .
           "tt<lastmod>$today</lastmod>n" .
           "tt<changefreq>monthly</changefreq>n" .
           "t</url>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" .
              "t</url>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 sitemaps.org, 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.

Share:

Categories: Technology

Previous and Next Articles (if any):

« »

Comments:

Your comment will appear below the form when it's approved. When the page redisplays after hitting the send button (it takes a few seconds), your comment has been sent.

When replying to someone else's comment, please start the comment with "@" and the name so I can put it in the right place.

More

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