How to add a sitemap of your Pod Page to WordPress Yoast SEO
Usually if you wanted to add Pods pages to your sitemaps, you would add the Pods SEO plugin. But that recently stopped working with Yoast, due to Yoast's changes in the admin structure ( With sitemap configuration admin pages missing, the pods plugin had nowhere to show the options any longer )
So the next best thing was to just quickly create our own sitemap rules programmatically. Let's say we have a pod called cars
and to access it, people can go to yourblogname.com/cars/{@permalink}
.
Now when we go to yourblogname.com/sitemap.xml
we want to not only see posts, pages, tags, categories, but also our cars section listed. And when you click on cars-sitemap.xml
we want all cars listed there as well, with their image, and the last modification time.
The search for a solution was a long one in the start, as the general yoast kb entry only tells us about the filters that limit the number of items per page, or remove items from the sitemap – but we want to add our own sitemap to Yoast SEO.
There is a vague entry that we can add an external sitemap by using the wpseo_sitemap_index
filter, but that's also not very helpful, as we want to generate the code for it – not just point to an existing file.
But it puts us on the right track of searching for examples based on wpseo_sitemap_index
and eventually you would find this great gist from mohandere which tells you how to add a sitemap for a custom post type.
It's slightly outdated with pointers by other people in the comments, and in our case we don't need the WordPress Queries as we want to work with pods.
So here's the few changes we need to make to adjust it to our own use-case :
- In the end we remove most of the custom logic, and just change it to Pods
- Change the outdated method calls to the new method names
- Move the filter priority to the end, so it wouldn't get overwritten by e.g. Pods SEO ( that was a big case that had me stumbling, as our sitemap data was seemingly ignored by wpseo_sitemap_index )
- Make the sitemap header work with images
You could add this code to the functions.php
file of your (child-)theme, or if you like to keep it clean, then save this as your_podname_sitemap.php
in your theme directory, and then add a include('your_podname_sitemap.php');
inside the functions.php
file.
We're assuming here that your cars
pod has a modified
field, which we can sort by, and that it has a picture
field, which has one image attached to it.
<?php
/**
* Creates a new custom yoast seo sitemap based on your pod
*/
// only use this during development to disable sitemap caching :
// add_filter( 'wpseo_enable_xml_sitemap_transient_caching', '__return_false');
add_filter( 'wpseo_sitemap_index', 'add_cars_sitemap_to_index', 99 );
add_action( 'init', 'add_cars_sitemap_to_wpseo' );
// Add custom index
function add_cars_sitemap_to_index($smp){
global $wpseo_sitemaps;
$car = pods('cars', array("orderby" => "modified DESC", "limit" => 1));
$date = $car->field('modified');
$smp .= '<sitemap>' . PHP_EOL;
$smp .= '<loc>' . site_url() .'/cars-sitemap.xml</loc>' . PHP_EOL;
$smp .= '<lastmod>' . htmlspecialchars( $date ) . '</lastmod>' . PHP_EOL;
$smp .= '</sitemap>' . PHP_EOL;
return $smp;
}
function add_cars_sitemap_to_wpseo(){
add_action( "wpseo_do_sitemap_car", 'generate_cars_sitemap');
}
function generate_cars_sitemap(){
global $wpseo_sitemaps;
$car = pods('cars', array("orderby" => "modified DESC", "limit" => -1) );
$output = '';
if( $car->total() > 0 ){
$chf = 'weekly';
$pri = 1.0;
while ( $car->fetch() ) {
$url = array();
$url['mod'] = $car->field('modified');
$url['loc'] = site_url() . '/car/' . $car->field('permalink');
$url['chf'] = $chf;
$url['pri'] = $pri;
$image = [];
if($car->field('picture.guid')) {
$image["src"] = $car->field('picture.guid');
$image["title"] = $car->field('name');
}
$url['images'] = [$image];
$output .= $wpseo_sitemaps->renderer->sitemap_url( $url );
}
}
//Build the full sitemap
$sitemap = '<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd http://www.google.com/schemas/sitemap-image/1.1 http://www.google.com/schemas/sitemap-image/1.1/sitemap-image.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . PHP_EOL;
$sitemap .= $output . '</urlset>';
$wpseo_sitemaps->set_sitemap($sitemap);
}
/*********************************************************
* OR we can use $wpseo_sitemaps->register_sitemap( 'car', 'METHOD' );
********************************************************/
add_action( 'init', 'register_cars_sitemap', 99 );
/**
* On init, run the function that will register our new sitemap as well
* as the function that will be used to generate the XML. This creates an
* action that we can hook into built around the new
* sitemap name - 'wp_seo_do_sitemap_*'
*/
function register_cars_sitemap() {
global $wpseo_sitemaps;
if($wpseo_sitemaps) {
$wpseo_sitemaps->register_sitemap( 'cars', 'generate_cars_sitemap' );
}
}
add_action( 'init', 'init_do_sitemap_actions' );
function init_do_sitemap_actions(){
add_action( 'wp_seo_do_sitemap_cars', 'generate_cars_sitemap' );
}
Make sure to clear your cache when testing your sitemaps. Now you should have your sitemap category listed when going to yoursite.com/sitemap.xml
, and you should also have a yoursite.com/cars-sitemap.xml
which would list all your items.