How to create image XML sitemap for posts, pages and Custom Post Type(CPT) in WordPress?

To generate/create Image XML Sitemap in WordPress properly, we need to use an action hook called publish_{$post->post_type} ( triggered whenever a post, page or Custom Post Type(CPT) is updated, or its new status is “publish” ).

Before seeing the complete code, we need to know about XML image sitemap required tags and its definition:

<image:image>(required) => Encloses all information about a single image. Each <url> tag can contian up to 1000 <image:image> tags.
<image:loc>(required) => The URL for the image.
<image:caption>(optional) => The caption of the image.
<image:title>(optional) => The title of the image.
<image:geo_location>(optional) => The geographic location of the image.
<image:license>(optional) => A URL to the license of the image.

I generated an image sitemap using posts, pages and Custom Post Type( CPT ) featured images and the images from the post content. I used a regular expression to get images from post content.

Here is the complete code to create an image XML Sitemap for post, page and Custom Post Type(CPT) in WordPress:

add_action( 'init', 'wpartisan_xml_image_sitemap_initialization' );

function wpartisan_xml_image_sitemap_initialization(){
	global $all_post_type_names;
	$default_posts_types = array(
		'page' => 'page',
		'post' => 'post',
	);
	$args = array(
		'public'   => true,
		'_builtin' => false,
	);
	$custom_post_types = get_post_types( $args, 'names' );
	$all_post_types = array_merge( $default_posts_types, $custom_post_types );
	$all_post_type_names = array_keys( $all_post_types );
	
	if( !empty( $all_post_type_names ) ) {
		foreach( $all_post_type_names as $post_type_name ):
			add_action( 'publish_'.$post_type_name, 'xml_image_sitemap', 10, 2 );
		endforeach;
	}
}

function xml_image_sitemap( $ID, $post ) {
	
	global $all_post_type_names;

	$sitemap = '<?xml version="1.0" encoding="UTF-8"?>';
	$sitemap .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">';
	
	foreach ( $all_post_type_names as $pty_name ) :
	
		if( $pty_name === 'page' ):
			$args = array(
				'sort_order' => 'desc',
				'sort_column' => 'post_modified',
				'hierarchical' => 1,
				'exclude' => '',
				'include' => '',
				'meta_key' => '',
				'meta_value' => '',
				'authors' => '',
				'child_of' => 0,
				'parent' => -1,
				'exclude_tree' => '',
				'number' => '',
				'offset' => 0,
				'post_type' => ''.$pty_name.'',
				'post_status' => 'publish'
			); 
			$posts = get_pages($args); 
		else:
			$args = array(
				'numberposts' => -1,
				'orderby'     => 'modified',
				'order'       => 'DESC',
				'exclude'     => '',
				'post_type'   => ''.$pty_name.'',
			);
			$posts = get_posts($args); 
		endif;
	
		if ( !empty( $posts ) ) {
			foreach( $posts as $post ) {
				setup_postdata($post);
				$page_url = get_permalink( $post->ID );
				
				$content = $post->post_content;
				$regex = '/src="([^"]*)"/';
				preg_match_all( $regex, $content, $matches );
				$matches = array_reverse($matches);

				if ( has_post_thumbnail( $post->ID ) || !empty( $matches[0] ) ) {
					
					$img = '';
					
					if( has_post_thumbnail( $post->ID ) ){
					
						$title = get_post(get_post_thumbnail_id($post->ID))->post_title;
					
						$img .= '<image:image>' . "\n";
							$img .= '<image:loc>' . get_the_post_thumbnail_url( $post->ID ) . '</image:loc>' . "\n";
							$img .= '<image:title>' . esc_html( $title ) . '</image:title>' . "\n";
						$img .= '</image:image>' . "\n";
					
					}
					
					if( !empty( $matches[0] ) ){
						foreach( $matches[0] as $content_image_url ){
							$img .= '<image:image>' . "\n";
								$img .= '<image:loc>' . $content_image_url . '</image:loc>' . "\n";
							$img .= '</image:image>' . "\n";
						}
					}
					
					$sitemap .= "<url>\n";
					$sitemap .= "<loc>" . $page_url . "</loc>\n";
					$sitemap .= $img;
					$sitemap .= "</url>\n";
				
				}

			}
		}
	endforeach;
	$sitemap .= '</urlset>';
	$fp = fopen(ABSPATH . "sitemap-media.xml", 'w');
	fwrite($fp, $sitemap);
	fclose($fp);
}
XML Sitemap example image
Image XML Sitemap

Leave a Reply

Your email address will not be published. Required fields are marked *