skip to Main Content

I’m using Yoast SEO plugin and I’m trying to exclude posts manually from posts XML sitemap using ‘wpseo_sitemap_entry’ filter but so far have no luck.

This is my current code:

function sitemap_exclude_post( $url, $type, $post) {
    if($post->ID == 6298 ) {
        return false;
    } 

return $url;
}
add_filter( 'wpseo_sitemap_entry', 'sitemap_exclude_post', 1, 3 );

Any suggestions will be much appreciated?

Note: I know it can be done via Yoast plugin’s backend by manually entering post IDs but I need to do it via filters. The above code is going to be further changed later to automatically obtain Post IDs of posts(single.php) from a category in wordpress.

4

Answers


  1. Chosen as BEST ANSWER

    The above code which I posted in my question works fine.

    I just pressed the "save changes" button inside Yoast’s dashboard "Exclude Posts" section and it worked. Not sure how, but it's working.


  2. You can easily do it from Yoast admin interface:

    https://kb.yoast.com/kb/sitemap-shows-excluded-posts-pages/

    Cheers,
    Francesco

    Login or Signup to reply.
  3. Can use update_option function.

    $array = array(
      "excluded-posts" => 6298
    );
    
    update_option('wpseo_xml', $array);
    

    Should be work also inside add_filter hook. update_option is a wp function that insert or update inside table options. The key inside wp_options table of Yoast SEO for XML Sitemap is wpseo_xml.
    In the value there is an array with other information:

    a:18: {
    s: 22: "disable_author_sitemap";
    b: 1;
    s: 22: "disable_author_noposts";
    b: 1;
    s: 16: "enablexmlsitemap";
    b: 1;
    s: 16: "entries-per-page";
    i: 1000;
    s: 14: "excluded-posts";
    s: 7: "1,2,3,4";
    s: 38: "user_role-administrator-not_in_sitemap";
    b: 0;
    s: 31: "user_role-editor-not_in_sitemap";
    b: 0;
    s: 31: "user_role-author-not_in_sitemap";
    b: 0;
    s: 36: "user_role-contributor-not_in_sitemap";
    b: 0;
    s: 35: "user_role-subscriber-not_in_sitemap";
    b: 0;
    s: 36: "user_role-authors_tes-not_in_sitemap";
    b: 0;
    s: 40: "user_role-authors_academy-not_in_sitemap";
    b: 0;
    s: 30: "post_types-post-not_in_sitemap";
    b: 0;
    s: 30: "post_types-page-not_in_sitemap";
    b: 0;
    s: 36: "post_types-attachment-not_in_sitemap";
    b: 1;
    s: 34: "taxonomies-category-not_in_sitemap";
    b: 0;
    s: 34: "taxonomies-post_tag-not_in_sitemap";
    b: 0;
    s: 37: "taxonomies-post_format-not_in_sitemap";
    b: 0;
    

    }

    Login or Signup to reply.
  4. I know the question has been answered already but I needed a more dynamical approach of what @clodclod91 explained and since I received the question more than once, I wrote some code about how to do this best in a ‘more fluid way’ than hardcoding any values.

    I hope it helps some people.

    I also wrote a post with a bit more explanation. Read it here.

    /**
     * Set all excluded items for sitemap in a transient
     *
     * @return mixed
     */
    function beee_get_sitemap_excludes_transient() {
    
        // get transient
        $output = get_transient( 'beee_exclude_sitemap' );
    
        // if transient returns false, create it
        if ( false == $output ) {
    
            $exclude_args = array(
                'post_type'      => [ 'page' ], // change this to the post types you want excluded
                'posts_per_page' => -1, // all items of course
                'meta_query'     => array(
                    array(
                        'key'     => 'beee_exclude_sitemap',
                        'value'   => '1',
                        'compare' => '=',
                    ),
                ),
                'orderby'        => 'ID',  // recommend to set to ID so 'the order is easier to compare later on', otherwise it can create issues
                'order'          => 'ASC', // same, just sort ASC to avoid issues
            );
            $excluded_items = get_posts( $exclude_args );
            if ( count( $excluded_items ) > 0 ) {
                // if there are items and create an empty array
                $exclude = [];
                foreach( $excluded_items as $item ) {
                    // add post id to array
                    $exclude[] = $item->ID;
                }
                // create a string from an array since Yoast stores a string, not an array
                $output = implode( ',', $exclude );
    
                // set transient with a 24-hour expiration
                set_transient( 'beee_exclude_sitemap', $output, 24 * HOUR_IN_SECONDS );
            }
        }
    
        return $output;
    }
    
    /**
     * Set Yoast settings from transient
     */
    function beee_exclude_pages_sitemap( $post_id ) {
    
        // get our excluded items from transient
        $our_excluded_posts = beee_get_sitemap_excludes_transient();
    
        // check if 'exclude' field has been set (in the post)
        if ( 1 == get_field( 'beee_exclude_sitemap', $post_id ) ) {
            // if yes, check if it exists in transient
            if ( in_array( $post_id, explode( ',', $our_excluded_posts ) ) ) {
                // yes, it's already included so we don't have to do anything
            } else {
                // no, it's not included so it needs to be added
                // so we delete the transient (existing values)
                delete_transient( 'beee_exclude_sitemap' );
            }
        } else {
            // it has not been set in the post
            if ( in_array( $post_id, explode( ',', $our_excluded_posts ) ) ) {
                // if does exists in our stored transient, which it shouldn't be in there
                // so we delete the transient (existing values)
                delete_transient( 'beee_exclude_sitemap' );
            }
        }
    
        // get our excluded ids from transient
        // since we just cleared it, the transient doesn't exist and is retrieved from scratch
        $our_excluded_posts = beee_get_sitemap_excludes_transient();
    
        // get post ids from Yoast settings
        $wpseo_xml = get_option( 'wpseo_xml' );
    
        // compare Yoast's value with our items
        if ( $wpseo_xml[ 'excluded-posts' ] == $our_excluded_posts ) {
            // they are the same so we don't need to do anything
        } else {
            // they are not the same so we need to update the database with our new ids
            update_option( 'wpseo_xml', $wpseo_xml );
        }
    }
    add_action( 'save_post', 'beee_exclude_pages_sitemap' );
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search