Exclude pages from wp-sitemap.xml in WordPress?

Add checkbox on all pages table in dashboard, to mark the pages will be exclude from wp-sitemap.xml

 This will involve several steps:

  1. First, let’s add a custom column to the pages table
  2. Add a checkbox for each page
  3. Save the excluded pages in WordPress options
  4. Add the filter to exclude the selected pages from the sitemap
<?php

if (!defined('ABSPATH')) {
    exit;
}

class Sitemap_Excluder {
    /**
     * The single instance of the class.
     *
     * @var Sitemap_Excluder
     */
    protected static $instance = null;

    /**
     * Option name for storing excluded pages
     *
     * @var string
     */
    private $option_name = 'sitemap_excluded_pages';

    /**
     * Main Sitemap_Excluder Instance.
     *
     * Ensures only one instance of Sitemap_Excluder is loaded or can be loaded.
     *
     * @return Sitemap_Excluder - Main instance.
     */
    public static function instance() {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Constructor.
     */
    private function __construct() {
        $this->init_hooks();
    }

    /**
     * Initialize hooks
     */
    private function init_hooks() {
        // Add custom column to pages table
        add_filter('manage_pages_columns', array($this, 'add_exclude_column'));
        
        // Add checkbox to the custom column
        add_action('manage_pages_custom_column', array($this, 'render_exclude_column'), 10, 2);
        
        // Add JavaScript to handle checkbox changes
        add_action('admin_footer', array($this, 'add_admin_javascript'));
        
        // Handle AJAX request
        add_action('wp_ajax_update_sitemap_exclusion', array($this, 'handle_ajax_update'));
        
        // Filter sitemap
        add_filter('wp_sitemaps_posts_query_args', array($this, 'filter_sitemap'), 10, 2);
    }

    /**
     * Add custom column to pages table
     *
     * @param array $columns Current columns.
     * @return array Modified columns.
     */
    public function add_exclude_column($columns) {
        $columns['exclude_sitemap'] = __('Sitemap', 'itc');
        return $columns;
    }

    /**
     * Render checkbox in custom column
     *
     * @param string $column_name Column being rendered.
     * @param int    $post_id     Post ID.
     */
    public function render_exclude_column($column_name, $post_id) {
        if ($column_name !== 'exclude_sitemap') {
            return;
        }
        
        $excluded_pages = $this->get_excluded_pages();
        $is_excluded = in_array($post_id, $excluded_pages);
        $icon_class = $is_excluded ? 'dashicons-no-alt' : 'dashicons-yes';
        $button_class = $is_excluded ? 'excluded' : 'not-excluded';
        
        printf(
            '<button type="button" class="sitemap-exclude-toggle %s" data-page-id="%d" data-excluded="%s">' .
            '<span class="dashicons %s"></span>' .
            '</button>',
            esc_attr($button_class),
            esc_attr($post_id),
            esc_attr($is_excluded ? 'true' : 'false'),
            esc_attr($icon_class)
        );
    }

    /**
     * Add JavaScript to admin footer
     */
    public function add_admin_javascript() {
        $screen = get_current_screen();
        if ($screen->id !== 'edit-page') {
            return;
        }
        ?>
        <style>
        .sitemap-exclude-toggle {
            background: none;
            border: none;
            padding: 0;
            cursor: pointer;
            color: #2271b1;
        }
        .sitemap-exclude-toggle.excluded {
            color: #d63638;
        }
        .sitemap-exclude-toggle:hover {
            color: #135e96;
        }
        .sitemap-exclude-toggle.excluded:hover {
            color: #d63638;
        }
        </style>
        <script>
        jQuery(document).ready(function($) {
            $('.sitemap-exclude-toggle').on('click', function(e) {
                e.preventDefault();
                var $button = $(this);
                var pageId = $button.data('page-id');
                var isExcluded = $button.data('excluded') === true;
                
                $.ajax({
                    url: ajaxurl,
                    type: 'POST',
                    data: {
                        action: 'update_sitemap_exclusion',
                        page_id: pageId,
                        is_checked: !isExcluded,
                        nonce: '<?php echo wp_create_nonce("sitemap_exclude_nonce"); ?>'
                    },
                    success: function(response) {
                        if (response.success) {
                            $button.data('excluded', !isExcluded);
                            $button
                                .toggleClass('excluded')
                                .find('.dashicons')
                                .toggleClass('dashicons-no-alt dashicons-yes');
                        }
                    }
                });
            });
        });
        </script>
        <?php
    }

    /**
     * Handle AJAX update request
     */
    public function handle_ajax_update() {
        check_ajax_referer('sitemap_exclude_nonce', 'nonce');
        
        if (!current_user_can('edit_pages')) {
            wp_send_json_error('Permission denied');
            return;
        }
        
        $page_id = intval($_POST['page_id']);
        $is_checked = $_POST['is_checked'] === 'true';
        
        $excluded_pages = $this->get_excluded_pages();
        
        if ($is_checked && !in_array($page_id, $excluded_pages)) {
            $excluded_pages[] = $page_id;
        } else if (!$is_checked) {
            $excluded_pages = array_diff($excluded_pages, array($page_id));
        }
        
        $this->update_excluded_pages($excluded_pages);
        wp_send_json_success();
    }

    /**
     * Filter sitemap to exclude selected pages
     *
     * @param array  $args      Query arguments.
     * @param string $post_type Post type.
     * @return array Modified query arguments.
     */
    public function filter_sitemap($args, $post_type) {
        if ($post_type === 'page') {
            $excluded_pages = $this->get_excluded_pages();
            if (!empty($excluded_pages)) {
                if (!isset($args['post__not_in'])) {
                    $args['post__not_in'] = array();
                }
                $args['post__not_in'] = array_merge($args['post__not_in'], $excluded_pages);
            }
        }
        return $args;
    }

    /**
     * Get excluded pages from options
     *
     * @return array Array of excluded page IDs
     */
    private function get_excluded_pages() {
        return get_option($this->option_name, array());
    }

    /**
     * Update excluded pages in options
     *
     * @param array $pages Array of page IDs to exclude
     */
    private function update_excluded_pages($pages) {
        update_option($this->option_name, $pages, false);
    }
}

// Load Sitemap Excluder
add_action('init', array('Sitemap_Excluder', 'instance'));


Comments

2 responses to “Exclude pages from wp-sitemap.xml in WordPress?”

  1. Где найти самые выгодные цены на стоматологию в Минске?, поспешите записаться.
    Стоматология цены https://total-implant.ru/ .

  2. Почему стоит использовать интерактивные сервисы для выбора имени для младенца, для раскрытия вашего творческого потенциала в выборе имени.
    Нумерология по имени и фамилии child-name.ru .