Skip to content

Instantly share code, notes, and snippets.

@amboutwe
Last active April 16, 2024 11:21
Show Gist options
  • Star 35 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save amboutwe/8cfb7a3d8f05e580867341d4ff84141d to your computer and use it in GitHub Desktop.
Save amboutwe/8cfb7a3d8f05e580867341d4ff84141d to your computer and use it in GitHub Desktop.
Filters and example code for Yoast SEO sitemaps
<?php
/********* DO NOT COPY THE PARTS ABOVE THIS LINE *********/
/* Create Custom Yoast Sitemap
* Credit: Unknown
* Last Tested: Unknown
*********
* HOW TO USE
* Replace TYPE with your custom type
*/
add_action( 'init', 'enable_custom_sitemap' );
function enable_custom_sitemap() {
global $wpseo_sitemaps;
if ( isset( $wpseo_sitemaps ) && ! empty ( $wpseo_sitemaps ) ) {
$wpseo_sitemaps->register_sitemap( 'TYPE', 'create_TYPE_sitemap' );
}
}
<?php
/********* DO NOT COPY THE PARTS ABOVE THIS LINE *********/
/* Add External Sitemap to Yoast Sitemap Index
* Credit: Paul https://wordpress.org/support/users/paulmighty/
* Modified by: Team Yoast
* Last Tested: Aug 25 2017 using Yoast SEO 5.3.2 on WordPress 4.8.1
*********
* This code adds two external sitemaps and must be modified before using.
* Replace http://www.example.com/external-sitemap-#.xml
with your external sitemap URL.
* Replace 2017-05-22T23:12:27+00:00
with the time and date your external sitemap was last updated.
Format: yyyy-MM-dd'T'HH:mm:ssZ
* If you have more/less sitemaps, add/remove the additional section.
*********
* Please note that changes will be applied upon next sitemap update.
* To manually refresh the sitemap, please disable and enable the sitemaps.
*/
add_filter( 'wpseo_sitemap_index', 'add_sitemap_custom_items' );
function add_sitemap_custom_items( $sitemap_custom_items ) {
$sitemap_custom_items .= '
<sitemap>
<loc>http://www.example.com/external-sitemap-1.xml</loc>
<lastmod>2017-05-22T23:12:27+00:00</lastmod>
</sitemap>';
/* Add Additional Sitemap
* This section can be removed or reused as needed
*/
$sitemap_custom_items .= '
<sitemap>
<loc>http://www.example.com/external-sitemap-2.xml</loc>
<lastmod>2017-05-22T23:12:27+00:00</lastmod>
</sitemap>';
/* DO NOT REMOVE ANYTHING BELOW THIS LINE
* Send the information to Yoast SEO
*/
return $sitemap_custom_items;
}
<?php
/********* DO NOT COPY THE PARTS ABOVE THIS LINE *********/
/* Change the number of entries per sitemap
* Credit: Yoast Team
* https://developer.yoast.com/features/xml-sitemaps/api/#alter-the-number-of-sitemap-entries
* Last Tested: Oct 17 2018 using Yoast SEO 8.4 on WordPress 4.9.8
* Limit should be either lower than 100 or a multiple of 100 to avoid problems with the sitemap pagination
*********
*/
add_filter( 'wpseo_sitemap_entries_per_page', 'max_entries_per_sitemap' );
function max_entries_per_sitemap() {
return 10;
}
Copy link

ghost commented Mar 8, 2018

@janw-oostendorp nailed the issue for me. The code would not call my filter, but disabling the caching corrected the issue.
Thanks,
Bill

@parsetty
Copy link

Thanks, Its working perfect cheers!!!!

@JakeLBeans
Copy link

Would like to add that this is currently still working with WordPress on 5.0.2 and Yoast plugin on 9.4!

@jack-fdrv
Copy link

jack-fdrv commented Jan 9, 2019

I have 3 questions:

  1. Why we use this part?
    $wpseo_sitemaps->register_sitemap( 'TYPE', 'create_TYPE_sitemap' );

  2. How to add my own custom link to the sub xml page? Like to the "/page-sitemap.xml"

  3. How to add sub pages to the http://www.example.com/external-sitemap-1.xml

@AlexL-JWA
Copy link

this code doesn’t work for me, I inserted it into function.php and it doesn’t show me my added sitemap
http://joxi.ru/l2ZLM6ETz1LEQr
http://joxi.ru/ZrJe4yGtwGDM4A

there are 18 of them and it remains to tell me what I'm doing wrong

@amboutwe
Copy link
Author

Please note that changes will be applied upon next sitemap update. To manually refresh the sitemap, please disable and enable the sitemaps.

If you have refreshed the sitemap, this is not the proper place to request support. Please check out our extensive Knowledge Base or visit the free support forum. If you require further support, upgrading to our premium version provides you with access to our support team.

@leepowers
Copy link

Two new gists as a more comprehensive examples. All in one file, including writing sitemap <url> tags with images:

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

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

@ziamediagroup
Copy link

Does anyone know how to REMOVE the line from the sitemap once you've added it? Even after refreshing the XML Sitemap option, and removing and reinstalling the plugin, that external sitemap is still showing

@amboutwe
Copy link
Author

Removing the code snippet will remove the custom functionality.

Additionally, this is not the proper place to request support. Please check out our extensive help section or visit the free support forum. If you require further support, upgrading to our premium version provides you with access to our support team.

@Sarasranglt
Copy link

Sarasranglt commented May 1, 2020

Two new gists as a more comprehensive examples. All in one file, including writing sitemap <url> tags with images:

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

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

@leepowers Thanks for this. This works.

@repl-tusar-rath
Copy link

I have 3 questions:

  1. How to add my own custom link to the sub xml page? Like to the "/page-sitemap.xml"

@jack-fdrv
Did you ever got a solution for this?

@Paulsky
Copy link

Paulsky commented Jan 5, 2021

Two new gists as a more comprehensive examples. All in one file, including writing sitemap <url> tags with images:

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

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

Thank you very much @leepowers!

@ROGMARQ14
Copy link

I can´t find yoast_seo_sitemap_add_external.php anywhere on the plugin editor tab.

A little help here?

Also, I want the new custom sitemap I want to create to be inside of /sitemap_index.xml...Thoughts?

@amboutwe
Copy link
Author

I can´t find yoast_seo_sitemap_add_external.php anywhere on the plugin editor tab.

That filename is the one from the example above. It is not part of the plugin and you will not see custom sitemaps in the plugin settings or edit screens/tabs.

I want the new custom sitemap I want to create to be inside of /sitemap_index.xml

The code snippet will add a link to the sitemap_index.xml file with all the other sub-sitemaps.

@robwent
Copy link

robwent commented Jul 4, 2021

Is it possible to use this multiple times?

I'm using it in a custom plugin but also run another plugin that uses it.

It seems that using it multiple times just overwrites the filters from the other plugins and only the last run filter will be added.

@amboutwe
Copy link
Author

amboutwe commented Jul 7, 2021

Yes, the code can be used multiple times. However, you will likely need to make changes to avoid overwriting. For example, changing the function name add_sitemap_custom_items to something unique. You can also add a priority level so one piece of code triggers before the other.

@robwent
Copy link

robwent commented Jul 7, 2021

I don't think it can be used multiple times?

Currently, another plugin is using the same filter to add a sitemap.

If I just use the same filter in my plugin then the sitemap only shows the filter from the first plugin.
if I increase the priority in my plugin then it overwrites the content added by the first plugin so my sitemap replaces the other one.

Both plugins have namespaced function names so I don't think that's the problem.

@amboutwe
Copy link
Author

amboutwe commented Jul 8, 2021

Before I sent my last reply, I tested the filter to add external sitemaps and was able to add 4 sitemaps, 2 from a plugin file and 2 from a theme's functions.php.

As that isn't happening in your setup, the issue is likely specific to your setup and this is not the proper place to request support. Please check out our extensive help section or visit the free support forum. If you require further support, upgrading to our premium version provides you with access to our support team.

@robwent
Copy link

robwent commented Jul 9, 2021

I found the problem.
The first plugin wasn't passing the $sitemap_custom_items variable into their custom function and just returning their own output.

So I had to up the priority in my own function and append my sitemap to theirs.

@freq32
Copy link

freq32 commented Feb 16, 2022

"function add_sitemap_custom_items" Confirmed working just now. thanks

@thematrixdev
Copy link

That filename is the one from the example above. It is not part of the plugin and you will not see custom sitemaps in the plugin settings or edit screens/tabs.

I cannot find all the three files. Where should I create them? Thanks.

@tongsonbarbs
Copy link

I have created a custom URL sitemap and have 1000+ urls in it. This code
`add_filter( 'wpseo_sitemap_entries_per_page', 'max_entries_per_sitemap' );

function max_entries_per_sitemap() {
return 10;
}`
is not working for the custom URL. But is working for the default sitemaps that were already there.

Any help for this?

@amboutwe
Copy link
Author

@tongsonbarbs I would guess that the method used to create the custom sitemap does not utilize the max entry limit. Adding a loop within the custom code should help.

If you're not familiar with loops, I'd recommend checking out Code Poet, WordPress Jobs, or WordPress Professional Network for development & consultancy.

@tongsonbarbs
Copy link

tongsonbarbs commented Mar 29, 2022

@amboutwe Thanks for your response.
Is there any method to create a custom sitemap that would utilize the max entry limit?

@Dewdan
Copy link

Dewdan commented Feb 1, 2023

thank you guys, this worked perfectly, added the code to my theme custom function.php and voilá!

Thanks

@llenegc
Copy link

llenegc commented Sep 14, 2023

thank you guys, this worked perfectly, added the code to my theme custom function.php and voilá!

Thanks

Hi @Dewdan! did you also include the yoast_seo_sitemap_add_custom_type.php and entries page code? I mean I just copy the yoast_seo_sitemap_add_external.php code then replace the link and the date. Then paste the those code in my theme file editor functions.php but it is not working.

@Dewdan
Copy link

Dewdan commented Sep 14, 2023

thank you guys, this worked perfectly, added the code to my theme custom function.php and voilá!
Thanks

Hi @Dewdan! did you also include the yoast_seo_sitemap_add_custom_type.php and entries page code? I mean I just copy the yoast_seo_sitemap_add_external.php code then replace the link and the date. Then paste the those code in my theme file editor functions.php but it is not working.

Hi @llenegc,

Can you paste your code here? It sounds like you might have missed something.
I didn't include that php, I just added the code into my child theme function.php. Make sure you create a.xml file and write in the code the right url. Mine is in the same directory as the wordpress directory.

add_filter( 'wpseo_sitemap_index', 'add_sitemap_custom_items' );

function add_sitemap_custom_items( $sitemap_custom_items ) {
   $sitemap_custom_items .= '
<sitemap>
<loc>**https://domainNAme/subdomain/menu-sitemap.xml**</loc>
<lastmod>2023-01-09T13:00:00+00:00</lastmod>
</sitemap>';

**return $sitemap_custom_items;**
}
 **?>**

@Pierre-Lavoine
Copy link

Pierre-Lavoine commented Oct 11, 2023

Hi all,

I have tried many things to optimise a website that having MySQL performance issue due to apparently Yoast

this is website have a sitemap of +1 300 pages with 1000urls each due to important bbpress forum

so I tried to exclude them and it work

but I would like something more advance like :
Keep only the 250 last URL of each type
or Kepp only the URL of the past week

The first function working but not the other one (I sued it once each not all function in same time)

/* Exclude Multiple Content Types From Yoast SEO Sitemap */
add_filter( 'wpseo_sitemap_exclude_post_type', 'sitemap_exclude_post_type', 10, 2 );

function sitemap_exclude_post_type( $value, $post_type ) {
	$post_type_to_exclude = array('topic','reply');
	if( in_array( $post_type, $post_type_to_exclude ) ) return true;
}*/


add_filter( 'wpseo_sitemap_entry', 'filter_yoast_sitemap_entries', 10, 3 );
function filter_yoast_sitemap_entries( $url, $type, $post ) {
    // Si le type de post est 'topic' ou 'reply'
    if ( in_array( $type, array( 'topic', 'reply' ) ) ) {
        // Si le post a été publié il y a plus d'une semaine, on l'exclut
        if ( strtotime( $post->post_date_gmt ) < strtotime( '-1 week' ) ) {
            return false;
        }
    }
    return $url;
}


function exclude_posts_from_yoast_sitemap( $excluded_posts_ids ) {
    $post_types = array( 'topic', 'reply' );

    foreach ( $post_types as $post_type ) {
        $posts = get_posts( array(
            'post_type'      => $post_type,
            'posts_per_page' => -1, // Récupère tous les posts
            'fields'         => 'ids', // Récupère seulement les IDs
            'date_query'     => array(
                array(
                    'column' => 'post_date',
                    'before' => '250 days ago', // Adaptez cette valeur si nécessaire
                ),
            ),
        ) );

        $excluded_posts_ids = array_merge( $excluded_posts_ids, $posts );
    }

    return $excluded_posts_ids;
}

add_filter( 'wpseo_exclude_from_sitemap_by_post_ids', 'exclude_posts_from_yoast_sitemap' );


function filter_yoast_sitemap_entries( $url, $type, $post ) {
    // Si le type de contenu est 'topic' ou 'reply'
    if ( 'post' === $type && ( 'topic' === $post->post_type || 'reply' === $post->post_type ) ) {
        // Récupère les 250 derniers posts de ce type
        $recent_posts = wp_get_recent_posts( array(
            'numberposts' => 250,
            'post_type'   => $post->post_type,
            'fields'      => 'ids',
        ) );
        // Si le post n'est pas dans les 250 derniers, ne l'ajoute pas au sitemap
        if ( ! in_array( $post->ID, $recent_posts ) ) {
            return false;
        }
    }
    return $url;
}

add_filter( 'wpseo_sitemap_entry', 'filter_yoast_sitemap_entries', 10, 3 );


function limit_yoast_sitemap_post_count( $count, $post_type ) {
    if ( 'topic' === $post_type || 'reply' === $post_type ) {
        return 250; // Limite à 250 URLs pour 'topic' et 'reply'
    }
    return $count; // Retourne le nombre par défaut pour les autres types de contenu
}

add_filter( 'wpseo_sitemap_post_type_archive_link_count', 'limit_yoast_sitemap_post_count', 10, 2 );

Do you have any ideas ?

I'm trying to optimise this SQL query actually :

SELECT l.ID, post_title, post_content, post_name, post_parent, post_author, post_status, post_modified_gmt, post_date, post_date_gmt
                        FROM (
                                SELECT WP_posts.ID
                                FROM WP_posts

                        WHERE WP_posts.post_status IN ('publish')
                                AND WP_posts.post_type = 'topic'
                                AND WP_posts.post_password = ''
                                AND WP_posts.post_date != '0000-00-00 00:00:00'

                                ORDER BY WP_posts.post_modified ASC LIMIT 100 OFFSET 101500
                        )
                        o JOIN WP_posts l ON l.ID = o.ID;

@amboutwe
Copy link
Author

This is not the proper place to request support. Please check out our extensive help section or visit the free support forum. If you require further support, upgrading to our premium version provides you with access to our support team.

@Dewdan
Copy link

Dewdan commented Oct 11, 2023

Thanks @amboutwe , I agree totally, you have been very helpful and it is now getting a little our of hand.

Cheers
:Dewdan

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