Skip to content

Instantly share code, notes, and snippets.

@mohandere
Last active September 25, 2024 18:47
Show Gist options
  • Save mohandere/4286103ce313d0cd6549 to your computer and use it in GitHub Desktop.
Save mohandere/4286103ce313d0cd6549 to your computer and use it in GitHub Desktop.
Wordpress yoast seo plugin, generate custom sitemap for custom URLS
<?php
/**
* Create a new custom yoast seo sitemap
*/
add_filter( 'wpseo_sitemap_index', 'ex_add_sitemap_custom_items' );
add_action( 'init', 'init_wpseo_do_sitemap_actions' );
// Add custom index
function ex_add_sitemap_custom_items(){
global $wpseo_sitemaps;
$date = $wpseo_sitemaps->get_last_modified('CUSTOM_POST_TYPE');
$smp ='';
$smp .= '<sitemap>' . "\n";
$smp .= '<loc>' . site_url() .'/CUSTOM_KEY-sitemap.xml</loc>' . "\n";
$smp .= '<lastmod>' . htmlspecialchars( $date ) . '</lastmod>' . "\n";
$smp .= '</sitemap>' . "\n";
return $smp;
}
function init_wpseo_do_sitemap_actions(){
add_action( "wpseo_do_sitemap_CUSTOM_KEY", 'ex_generate_origin_combo_sitemap');
}
function ex_generate_origin_combo_sitemap(){
global $wpdb;
global $wp_query;
global $wpseo_sitemaps;
$post_type = 'CUSTOM_POST_TYPE';
wp_reset_query();
$args = array(
'posts_per_page' => -1,
'orderby' => 'post_date',
'order' => 'DESC',
'post_type' => $post_type,
'post_status' => 'publish',
'suppress_filters' => true
);
query_posts( $args );
wp_reset_postdata();
//echo '<pre>';print_r($url);echo '</pre>';
$posts_array = get_posts( $args );
$output = '';
if( !empty( $posts_array ) ){
$chf = 'weekly';
$pri = 1.0;
foreach ( $posts_array as $p ) {
$p->post_type = $post_type;
$p->post_status = 'publish';
$p->filter = 'sample';
$url = array();
if ( isset( $p->post_modified_gmt ) && $p->post_modified_gmt != '0000-00-00 00:00:00' && $p->post_modified_gmt > $p->post_date_gmt ) {
$url['mod'] = $p->post_modified_gmt;
} else {
if ( '0000-00-00 00:00:00' != $p->post_date_gmt ) {
$url['mod'] = $p->post_date_gmt;
} else {
$url['mod'] = $p->post_date;
}
}
$url['loc'] = site_url().'/sample/all/'.$p->post_name;
$url['chf'] = $chf;
$url['pri'] = $pri;
$output .= $wpseo_sitemaps->sitemap_url( $url );
// Clear the post_meta and the term cache for the post, as we no longer need it now.
// wp_cache_delete( $p->ID, 'post_meta' );
// clean_object_term_cache( $p->ID, $post_type );
}
}
// Grab last modified date
$sql = $wpdb->prepare(" SELECT MAX(p.post_modified_gmt) AS lastmod
FROM $wpdb->posts AS p
WHERE post_status IN ('publish') AND post_type = %s ", $post_type );
$mod = $wpdb->get_var( $sql );
// Generate terms URLs
$practitioner_terms = get_terms( 'TAXONOMY', 'orderby=count&hide_empty=0' );
if( !empty( $practitioner_terms ) ){
$pri = 1;
$chf = 'weekly';
foreach ($practitioner_terms as $key => $term ){
$url = array();
$url['loc'] = site_url().'/sample/'.$term->slug;
$url['pri'] = $pri;
$url['mod'] = $mod;
$url['chf'] = $chf;
$output .= $wpseo_sitemaps->sitemap_url( $url );
}
}
// Generate permutation & combinations
if( ( !empty( $practitioner_terms) ) && ( ! empty($posts_array ) ) ){
$pri = 1;
$chf = 'weekly';
wp_reset_postdata();
foreach ($practitioner_terms as $key => $term ){
$args = array(
'posts_per_page' => -1,
'orderby' => 'post_date',
'order' => 'DESC',
'post_type' => $post_type,
'post_status' => 'publish',
'suppress_filters' => true,
'tax_query' => array(
array(
'taxonomy' => 'TAXONOMY',
'field' => 'slug',
'terms' => $term->slug,
'operator' => 'IN'
),
),
);
$posts_array = get_posts( $args );
//echo '<pre>';print_r($posts_array);echo '</pre>';
$url = array();
foreach ($posts_array as $key => $p ){
$url['loc'] = site_url().'/sample/'.$term->slug.'/'.$p->post_name;
$url['pri'] = $pri;
$url['mod'] = $mod;
$url['chf'] = $chf;
$output .= $wpseo_sitemaps->sitemap_url( $url );
}
}
}
if ( empty( $output ) ) {
$wpseo_sitemaps->bad_sitemap = true;
return;
}
//Build the full sitemap
$sitemap = '<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ';
$sitemap .= 'xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" ';
$sitemap .= 'xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
$sitemap .= $output . '</urlset>';
//echo $sitemap;
$wpseo_sitemaps->set_sitemap($sitemap);
}
/*********************************************************
* OR we can use $wpseo_sitemaps->register_sitemap( 'CUSTOM_KEY', 'METHOD' );
********************************************************/
add_action( 'init', 'ex_register_my_new_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_my_new_sitemap'
*/
function ex_register_my_new_sitemap() {
global $wpseo_sitemaps;
$wpseo_sitemaps->register_sitemap( 'CUSTOM_KEY', 'ex_generate_origin_combo_sitemap' );
}
add_action( 'init', 'init_do_sitemap_actions' );
function init_do_sitemap_actions(){
add_action( 'wp_seo_do_sitemap_our-CUSTOM_KEY', 'ex_generate_origin_combo_sitemap' );
}
@Greenlanternfromhouston

How do you use this? I've been struggling for hours trying to add my own custom sitemap url to yoast 5.0 's sitemap_index.xml. I will not add any new ones.

I tried your post as well as this other post https://kb.yoast.com/kb/add-external-sitemap-to-index/ , added to my child theme's function.php, even tried adding to my main functions.php. It will NOT add custom sitemaps.

What am I missing? Am missing a add_action command??
How do you configure yours to add for instance a sitemap named MYMAIN_sitemap.xml MYsecondary_sitemap.xml to the sitemap_index.xml

@cjbrooks12
Copy link

After searching for a while, I found in the Yoast docs that sitemaps are cached and needed to be disabled, then reenabled for these entries to actually show up in the generated sitemaps.

@haroldkyle
Copy link

Line 161 will cause a deprecation warning: Notice: WPSEO_Sitemaps::sitemap_url is deprecated since version WPSEO 3.2! Use WPSEO_Sitemaps_Renderer::sitemap_url() instead.

To fix this, change line 161 to:

$output .= $wpseo_sitemaps->renderer->sitemap_url( $url );

@gdelwo
Copy link

gdelwo commented Oct 27, 2017

Hello, I get the following error:

The following file is blocking your XML sitemaps from working properly. Either delete it (this can be done with the "Fix it" button) or disable Yoast SEO XML sitemaps.
domain/sitemap.xml

any suggestions? thks in advance

@hassan-alvi
Copy link

hassan-alvi commented Mar 13, 2018

With an updated version of YOAST 7.0.3 .., the entries per page option is not working at all .. any way around it?

$wpseo_options = WPSEO_Options::get_all();
$sitemap_entries_per_page = $wpseo_options['entries-per-page'];

@sandeepg2755
Copy link

sandeepg2755 commented Sep 13, 2018

Line 161 will cause a deprecation warning: Notice: WPSEO_Sitemaps::sitemap_url is deprecated since version WPSEO 3.2! Use WPSEO_Sitemaps_Renderer::sitemap_url() instead.

To fix this, change line 161 to:

$output .= $wpseo_sitemaps->renderer->sitemap_url( $url );

thanks for that @haroldkyle

@mastef
Copy link

mastef commented Dec 16, 2018

Thanks for this post and the comments. I have made an adjusted version of this implementation that allows you to add yoast sitemaps with custom Pods / Pods Pages.

@mastef
Copy link

mastef commented Dec 16, 2018

In the filter, you want to "add" instead of overwriting right now. Otherwise if you do this multiple times, you'll just have the latest sitemap function that ran. So you'd want these changes to add multiple sitemap indexes :

-function ex_add_sitemap_custom_items(){
+function ex_add_sitemap_custom_items($smp){
	global $wpseo_sitemaps;
	$date = $wpseo_sitemaps->get_last_modified('CUSTOM_POST_TYPE');

-	$smp ='';

    	$smp .= '<sitemap>' . "\n";

@davejtoews
Copy link

Why is ex_generate_origin_combo_sitemap() assigned to two different hooks AND register_sitemap()? Shouldn't register_sitemap() alone suffice? Is this a backwards compatibility thing?

@samuelcerezo
Copy link

Thanks for the snippet. Modifying it a bit to adapt it to the latest Yoast version works like a charm. :)

@leepowers
Copy link

Why is ex_generate_origin_combo_sitemap() assigned to two different hooks AND register_sitemap()? Shouldn't register_sitemap() alone suffice? Is this a backwards compatibility thing?

Yes - only register_sitemap() is required. Lines like add_action( "wpseo_do_sitemap_CUSTOM_KEY", '....'); are redundant as register_sitemap() already adds these actions, see line 165 of the Yoast source class.

Just added two new gists as a more comprehensive examples. All in one file, including writing sitemap <url> tags with images. Don't have all the extra "practitioner" cruft.

Sitemap without a data source specified:
https://gist.github.com/leepowers/2b32f734571cbeadc811b93501cfcced

Sitemap sourced from post type(s):
https://gist.github.com/leepowers/946d9c72e06779acbb2a125e5b53f475

@pedrogusmao02
Copy link

Exactly what I was looking for, thanks!

@intelligentdharmesh
Copy link

I am getting 404 - page not found in my staging environment after generating custom sitemap using this code. Please suggest a fix for this. I have already saved permalink, cleared all kind of cache but still not working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment