Skip to main content

Overview

XML Sitemaps help search engines discover and index your content efficiently. GEO AI automatically generates standards-compliant sitemaps with support for images, custom post types, and taxonomies.
Sitemaps help search engines crawl your site 30-50% more efficiently, especially for large sites.

Features

Sitemap Index

Main sitemap.xml that links to individual post type sitemaps

Post Type Sitemaps

Separate sitemaps for posts, pages, and custom post types

Image Sitemaps

Includes featured images and inline images in sitemap entries

Auto-Update

Updates automatically when content is published or modified

Sitemap URLs

Once enabled, your sitemaps are available at:
https://yoursite.com/sitemap.xml

Configuration

1

Access Sitemap Settings

Navigate to Settings → GEO AI → Sitemaps
2

Enable Sitemaps

Check “Generate XML sitemaps” to enable the feature
3

Configure Options

  • Enable “Add image URLs to sitemaps” for image support
  • Select post types to include (posts, pages, custom post types)
4

Save & Flush

Click Save Changes, then go to Settings → Permalinks and click Save Changes to flush rewrite rules
Always flush permalinks after enabling sitemaps, or you’ll get 404 errors when accessing sitemap URLs.

Implementation Details

Sitemap Class

includes/class-geoai-sitemaps.php
class GeoAI_Sitemaps {
    private static $instance = null;

    public static function get_instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        add_action( 'init', array( $this, 'add_rewrite_rules' ) );
        add_action( 'template_redirect', array( $this, 'serve_sitemap' ) );
    }

    public function add_rewrite_rules() {
        add_rewrite_rule( '^sitemap\.xml$', 'index.php?geoai_sitemap=index', 'top' );
        add_rewrite_rule( '^sitemap-([^/]+)\.xml$', 'index.php?geoai_sitemap=$matches[1]', 'top' );
        
        add_rewrite_tag( '%geoai_sitemap%', '([^&]+)' );
    }
}

Sitemap Index Generation

includes/class-geoai-sitemaps.php
private function generate_sitemap_index() {
    $xml = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    $xml .= '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";

    $settings = get_option( 'geoai_sitemaps', array() );
    $post_types = $settings['post_types'] ?? array( 'post', 'page' );

    foreach ( $post_types as $post_type ) {
        $xml .= sprintf(
            '<sitemap><loc>%s</loc><lastmod>%s</lastmod></sitemap>' . "\n",
            esc_url( home_url( "/sitemap-{$post_type}.xml" ) ),
            esc_xml( current_time( 'c' ) )
        );
    }

    $xml .= '</sitemapindex>';
    
    return $xml;
}

Individual Sitemap Generation

includes/class-geoai-sitemaps.php
private function generate_sitemap( $type ) {
    $xml = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    $xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">' . "\n";

    $posts = get_posts(
        array(
            'post_type'      => $type,
            'post_status'    => 'publish',
            'posts_per_page' => 1000,
            'orderby'        => 'modified',
            'order'          => 'DESC',
        )
    );

    foreach ( $posts as $post ) {
        $xml .= '<url>' . "\n";
        $xml .= sprintf( '<loc>%s</loc>' . "\n", esc_url( get_permalink( $post ) ) );
        $xml .= sprintf( '<lastmod>%s</lastmod>' . "\n", esc_xml( get_the_modified_date( 'c', $post ) ) );
        $xml .= '<changefreq>weekly</changefreq>' . "\n";
        $xml .= '<priority>0.8</priority>' . "\n";

        $settings = get_option( 'geoai_sitemaps', array() );
        if ( ! empty( $settings['images'] ) ) {
            $thumbnail = get_the_post_thumbnail_url( $post, 'full' );
            if ( $thumbnail ) {
                $xml .= sprintf( '<image:image><image:loc>%s</image:loc></image:image>' . "\n", esc_url( $thumbnail ) );
            }
        }

        $xml .= '</url>' . "\n";
    }

    $xml .= '</urlset>';
    
    return $xml;
}

Serving Sitemaps

includes/class-geoai-sitemaps.php
public function serve_sitemap() {
    $sitemap = get_query_var( 'geoai_sitemap' );
    
    if ( ! $sitemap ) {
        return;
    }

    $settings = get_option( 'geoai_sitemaps', array() );
    
    if ( empty( $settings['enabled'] ) ) {
        return;
    }

    header( 'Content-Type: application/xml; charset=utf-8' );
    
    if ( 'index' === $sitemap ) {
        $output = $this->generate_sitemap_index();
    } else {
        $output = $this->generate_sitemap( $sitemap );
    }

    echo $output;
    
    exit;
}

Sitemap Structure

Sitemap Index Example

<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <sitemap>
    <loc>https://example.com/sitemap-post.xml</loc>
    <lastmod>2025-03-04T15:30:00+00:00</lastmod>
  </sitemap>
  <sitemap>
    <loc>https://example.com/sitemap-page.xml</loc>
    <lastmod>2025-03-04T15:30:00+00:00</lastmod>
  </sitemap>
</sitemapindex>

Individual Sitemap Example

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" 
        xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
  <url>
    <loc>https://example.com/wordpress-performance/</loc>
    <lastmod>2025-03-04T10:00:00+00:00</lastmod>
    <changefreq>weekly</changefreq>
    <priority>0.8</priority>
    <image:image>
      <image:loc>https://example.com/wp-content/uploads/featured.jpg</image:loc>
    </image:image>
  </url>
  <url>
    <loc>https://example.com/seo-guide/</loc>
    <lastmod>2025-03-03T14:20:00+00:00</lastmod>
    <changefreq>weekly</changefreq>
    <priority>0.8</priority>
  </url>
</urlset>

Sitemap Elements

Required. The full URL of the page.
<loc>https://example.com/my-post/</loc>
Optional. Last modification date in ISO 8601 format.
<lastmod>2025-03-04T15:30:00+00:00</lastmod>
GEO AI uses the post’s post_modified date.
Optional. How frequently the page likely changes.
<changefreq>weekly</changefreq>
GEO AI defaults to “weekly” for all pages.Values: always, hourly, daily, weekly, monthly, yearly, never
Optional. Relative priority of this URL (0.0 to 1.0).
<priority>0.8</priority>
GEO AI defaults to 0.8 for all pages.
Optional. Featured image URL for the page.
<image:image>
  <image:loc>https://example.com/image.jpg</image:loc>
</image:image>
Only included when “Add image URLs” is enabled.

Submitting to Search Engines

1

Open Search Console

2

Select Property

Choose your website property
3

Go to Sitemaps

Click Sitemaps in the left sidebar
4

Add Sitemap

Enter sitemap.xml and click Submit
5

Monitor Status

Check back in 24-48 hours to see discovered URLs

Image Sitemaps

When enabled, GEO AI adds image extensions to help search engines discover images:
<url>
  <loc>https://example.com/my-post/</loc>
  <image:image>
    <image:loc>https://example.com/wp-content/uploads/featured.jpg</image:loc>
  </image:image>
</url>
Benefits:
  • Helps images appear in Google Image Search
  • Improves image discoverability
  • Useful for image-heavy sites (portfolios, galleries)
Enable image sitemaps if your content relies heavily on visual assets.

Sitemap Limits

URL Limit

50,000 URLs per sitemap fileGEO AI currently limits to 1,000 posts per sitemap for performance

File Size Limit

50 MB uncompressedTypical WordPress sites rarely approach this limit
If you exceed 1,000 posts:
  • Consider excluding old/outdated content
  • Use pagination (planned for future update)
  • Split by taxonomy (planned for future update)

Excluding Content

Exclude specific posts from sitemaps:
add_filter( 'geoai_sitemap_exclude_post', 'exclude_from_sitemap', 10, 2 );

function exclude_from_sitemap( $exclude, $post ) {
    // Exclude posts with 'noindex' robots meta
    $robots = get_post_meta( $post->ID, '_geoai_robots', true );
    if ( strpos( $robots, 'noindex' ) !== false ) {
        return true;
    }
    
    // Exclude specific categories
    if ( has_category( 'uncategorized', $post ) ) {
        return true;
    }
    
    return $exclude;
}

Best Practices

Submit Early

Submit your sitemap to search engines as soon as you launch your site.

Monitor Regularly

Check Google Search Console monthly for sitemap errors or warnings.

Keep It Fresh

Sitemaps update automatically when content changes. No manual intervention needed.

Use Selective Inclusion

Only include post types that should be indexed. Exclude admin pages, drafts, etc.

Flush Permalinks

Always flush rewrite rules after enabling/disabling sitemaps.

Include in robots.txt

Reference your sitemap in robots.txt for maximum discoverability.

Troubleshooting

Cause: Rewrite rules not flushedSolution:
  1. Go to Settings → Permalinks
  2. Click “Save Changes” (no changes needed)
  3. Try accessing sitemap.xml again
Check:
  • Sitemaps are enabled in Settings → Sitemaps
  • You have published posts/pages (not drafts)
  • The post type is selected in settings
Check:
  • “Add image URLs to sitemaps” is enabled
  • Posts have featured images set
  • Image URLs are publicly accessible
Cause: Multiple SEO plugins generating sitemapsSolution: Enable Coexist Mode or disable sitemaps in other plugins
Common issues:
  • Invalid lastmod dates (check post modified dates)
  • Broken image URLs (verify featured images)
  • Redirect chains (fix redirect issues)
Use Google Search Console to identify specific errors.

Validation

Validate your sitemap structure:
1

Access Sitemap

Visit https://yoursite.com/sitemap.xml in a browser
2

Validate XML

Use an XML Validator to check syntax
3

Check Sitemap Protocol

Verify against Sitemaps.org protocol
4

Test in Search Console

Submit to Google Search Console and check for errors

Performance Considerations

Caching

Sitemaps are generated on-the-fly. Consider caching for high-traffic sites.

Query Limits

Default limit of 1,000 posts prevents database overload on large sites.

Enable Caching

add_filter( 'geoai_sitemap_cache_duration', function() {
    return 3600; // Cache for 1 hour
});

Robots Meta

Control indexing per post

Schema Markup

Structured data for search

AI Crawler Control

Manage AI bot access

Build docs developers (and LLMs) love