Add Featured Image To Accelerated Mobile Pages in WordPress

 

Update: The AMP plugin now shows the featured image, so this code is not really needed anymore (since AMP version 0.4).

 
This is how you can add the featured image (post thumbnail) to the Accelerated Mobile Pages (AMP) template in WordPress. This is only for people that use the WordPress AMP plugin by Automattic.

You’ll notice that the AMP plugin does not add the featured image (post thumbnail) to the single post template. The AMP template will show images that you add to your post content, but it will not show the actual “featured image.”

You cannot simply use the the_post_thumbnail() because Accelerated Mobile Pages do not allow the img element. So, if you use the_post_thumbnail(), your AMP pages will not validate. You’ll get AMP validation errors like these, for example:

The attribute ‘sizes’ may not appear in tag ‘img’.
The tag ‘img’ may only appear as a descendant of tag ‘noscript’. Did you mean ‘amp-img’?

The correct way to add an image to Accelerated Mobile Pages is to use the ‘amp-img’ element. We’ll do that.

Here, I show you how to add a template tag to the AMP “single.php” template. The WP AMP plugin lets you copy their “single.php” template to your own theme so you can modify it.

So, go ahead and do that first. Copy the AMP template into your theme like this:
Create a folder named “amp” inside your theme. Inside that “amp” folder (/your_theme/amp/), create a new file called “single.php”. In that file, paste a copy of the AMP plugin’s “single.php” template. You can find their “single.php” inside the plugin’s “template” folder. Here is a link to the raw text of the actual file on the WordPress plugin repository so that you can easily copy all of the text from that file. Now, paste it into your newly-created “single.php” inside your theme’s “amp” folder. Save it.

Now you can modify the “single.php” as you wish.

We’re going to create a template tag, isa_amp_featured_img(), for the AMP template that will display the post’s featured image.

To create the template tag, paste this code into a functions file (any way you do this is fine, whether in your child theme’s functions.php, or a plugin, etc.):

/**
 * Template tag to show featured image on AMP
 * @param string $size the post thumbnail size
 */
function isa_amp_featured_img( $size = 'medium' ) {

    global $post;
    
    if ( has_post_thumbnail( $post->ID ) ) {

        $thumb_id = get_post_thumbnail_id( $post->ID );
        $img = wp_get_attachment_image_src( $thumb_id, $size );
        $img_src = $img[0];
        $w = $img[1];
        $h = $img[2];

		$alt = get_post_meta($post->ID, '_wp_attachment_image_alt', true);
        
		if(empty($alt)) {
			$attachment = get_post( $thumb_id );
			$alt = trim(strip_tags( $attachment->post_title ) ); 
		} ?>
		<amp-img id="feat-img" src="<?php echo esc_url( $img_src ); ?>" <?php
			if ( $img_srcset = wp_get_attachment_image_srcset( $thumb_id, $size ) ) {
				?> srcset="<?php echo esc_attr( $img_srcset ); ?>" <?php
			}
			?> alt="<?php echo esc_attr( $alt ); ?>" width="<?php echo $w; ?>" height="<?php echo $h; ?>">
		</amp-img>
		<?php
	}
}

/**
 * Make AMP use your custom single.php.
 */
function my_amp_set_custom_template( $file, $type, $post ) {
    if ( 'single' === $type ) {
        $file =  get_stylesheet_directory() . '/amp/single.php';
    }
    return $file;
}
add_filter( 'amp_post_template_file', 'my_amp_set_custom_template', 10, 3 );

Usage

To use the template tag, just place the tag, isa_amp_featured_img(); somewhere in your theme’s /amp/single.php file. Place it where you want to display the featured image.

Depending on where you place it inside your template, you may need to enclose it in PHP tags.

The template tag accepts one parameter: size. This refers to the four official WordPress post thumbnail sizes. These are:

‘thumbnail’
‘medium’
‘large’
‘full’

By default, if you don’t pass a parameter, the ‘medium’ thumbnail size will be used. You can pass any of the four sizes as a parameter. For example, to use the thumbnail size instead of the default ‘medium’, use:

isa_amp_featured_img( 'thumbnail' );

Now you have a featured image on your Accelerated Mobile Pages, and it validates with AMP.

See more: ,

We've 22 Responses

  1. February 15th, 2016 at 3:28 pm

    Isabel,

    Have you tested this? getting server 500 and if I validate code online, there are few syntax errors like unexpected } line 22 etc.. even if fixed syntax error, still getting server 500 error. PHP version is 5.3.

    Any ideas?

    Thanks,

    Tester
  2. February 16th, 2016 at 12:22 am

    I’m getting error code

    Warning: include(/home/tricialo/public_html/wp-content/themes/twentyeleven/amp/single.php): failed to open stream: No such file or directory in /home/tricialo/public_html/wp-content/plugins/amp/includes/class-amp-post-template.php on line 225
    
    Warning: include(): Failed opening '/home/tricialo/public_html/wp-content/themes/twentyeleven/amp/single.php' for inclusion (include_path='.:/usr/lib/php:/usr/local/lib/php') in /home/tricialo/public_html/wp-content/plugins/amp/includes/class-amp-post-template.php on line 225
    
    Aaron D
    • February 16th, 2016 at 12:20 pm

      It was searching your Twenty Eleven parent theme for the template. I updated the code again, just now, to accommodate child themes, as well. Thanks for your patience and error reporting.

      Isabel
  3. April 4th, 2016 at 2:44 pm

    Hi Isabel,

    This and your other bits of AMP code are just fantastic – thank you so much!

    I’m wondering whether there can be a similar workaround for themes (like mine) that offer a Video custom post using a featured video instead of a featured image? If not then I’m just going to have to stop using this post format, since these posts make no sense with the featured video being stripped away.

    Thanks,

    Sergio

    Sergio
  4. April 28th, 2016 at 5:02 pm

    Hi Isabel,

    Thanks for the post, it was very useful.

    A couple of things I added to the code were: add tag layout=”responsive” to make the featured image responsive. Making the code:

            <amp-img id="feat-img" layout="responsive" src="<?php echo esc_url( $img_src ); ?>" <?php
                if ( $img_srcset = wp_get_attachment_image_srcset( $thumb_id, $size ) ) {
                    ?> srcset="<?php echo esc_attr( $img_srcset ); ?>" <?php
                }
                ?> alt="<?php echo esc_attr( $alt ); ?>" width="<?php echo $w; ?>" height="<?php echo $h; ?>">
            </amp-img>
    

    And make the image display based on the category for eg:

        <?php if ( in_category('stories') ) : ?>
            <?php echo isa_amp_featured_img( 'large' ); ?>
        <?php endif; ?>
    

    Thought this would help others.

    shashi
  5. October 26th, 2016 at 9:50 am

    Sorry in advance cause I don’t really know where in the site I post for this.
    Is there a way that I can I run the AMP automatically when am on mobile view instead of having to type /amp immediate after the link?

    Sidney
    • October 26th, 2016 at 1:06 pm

      Hi. No, Google (and other AMP consumers) decide when to show AMP pages. We don’t get any control over that. If you like your AMP design, what you can do is copy the AMP CSS and modify it as needed to apply to your main theme, then add that CSS to your site using CSS @media queries to target only small screens. That way, you can make your main site look just like AMP pages on mobile.

      Isabel
      • November 22nd, 2016 at 8:53 pm

        Hi, yes, this code is for that same AMP plugin. The following code will take the first image that is added to the body of your post content, and it will add that image above the content on AMP pages. If a post does not have an image added to the content body, then it will do nothing. This code all goes in a functions file. See if that helps. (However this is not the best to use on AMP pages because it uses “preg_match” which uses a lot of memory. Could your featured images be missing because maybe you’re using a custom /amp/single.php template file that has not been updated to the lastest AMP version? Perhaps updating that template file would fix the issue.)

        /**
         * Maybe add an image to AMP above the content
         */
        add_action( 'pre_amp_render_post', 'isa_amp_add_custom_actions' );
        function isa_amp_add_custom_actions() {
        	add_filter( 'the_content', 'isa_amp_above_content' );
        }
        function isa_amp_above_content( $content ) {
        	
        	// extract first image from post content
         
        	$img_start = strpos( $content, '<img', 0 );
         
        	if ( $img_start ) {
        
        		$post = substr( $content, $img_start );
        		$img_end = strpos( $post, '>' );
        		$image_tag = substr( $post, 0, $img_end+1 );
        
        		// Extract image src
        		preg_match('/(src=["\'](.*?)["\'])/', $image_tag, $match_src); //find src="X" or src='X'
        		$split_src = preg_split('/["\']/', $match_src[0]); // split by quotes
        		$img_src = isset( $split_src[1] ) ? $split_src[1] : ''; // X between quotes
        
        		// Extract image width
        		preg_match('/(width=["\'](.*?)["\'])/', $image_tag, $match_width); //find width="X" or width='X'
        		$split_width = preg_split('/["\']/', $match_width[0]); // split by quotes
        		$img_width = isset( $split_width[1] ) ? $split_width[1] : ''; // X between quotes
        
        		// Extract image height
        		preg_match('/(height=["\'](.*?)["\'])/', $image_tag, $match_height); //find height="X" or height='X'
        		$split_height = preg_split('/["\']/', $match_height[0]); // split by quotes
        		$img_height = isset( $split_height[1] ) ? $split_height[1] : ''; // X between quotes		
        
        		// If we have an image src, add the image above the content
        
        		if ( $img_src ) {
        
        			$content = '<amp-img id="feat-img" src="' . esc_url( $img_src ) . '" alt="" width="' . $img_width . '" height="' . $img_height . '"></amp-img>' . $content;
        		
        		}
        
        	}
        
        	return $content;
        }
        
        Isabel
  6. December 4th, 2016 at 1:05 pm

    The following adapts your featured image code into a function which provides valid JSON data. If no featured image exists, a default image is provided.

    As of Dec 2016 my posts with – or without – featured images pass Google AMP validation. Note I am using the GeneratePress WP theme.

    Note default images are placed inside the “amp” folder of my theme, similar to your recommendation for the edited single.php AMP template.

    function amp_modify_json_metadata($metadata, $post) {
       global $post;
       
       if( 'post'=== $post->post_type  ){
       $metadata['@type'] = 'Article';
       $metadata['publisher']['name'] = 'YOUR-PUBLISHER-NAME';
       $metadata['publisher']['logo'] = array(
            '@type' => 'ImageObject',
            'url' => get_stylesheet_directory_uri().'/amp/YOUR-LOGO-IMAGE.jpg',
            'height' => 60,
            'width' => 600
        );
    	/* If Image, use featured Image in AMP JSON */
    	if (has_post_thumbnail($post->ID) )
    		{
            $thumb_id = get_post_thumbnail_id( $post->ID );
            $img = wp_get_attachment_image_src( $thumb_id, $size );
            $img_src = $img[0];
            $w = $img[1];
            $h = $img[2];
    	
    		$metadata['image'] = array(
            '@type' => 'ImageObject',
            'url' => ''.$img_src.'',
            'height' => ''.$h.'',
            'width' => ''.$w.''
    		); 
    		} /* If Post has Featured Image */
    	else
    	/* If No Image, use a default */
    		{
    		$metadata['image'] = array(
            '@type' => 'ImageObject',
            'url' => get_stylesheet_directory_uri().'/amp/YOUR-DEFAULT-IMAGE.jpg',
            'height' => 800,
            'width' => 800
    		); 
    		} /* Else No Image, use a default */
    		
    	/* Some RSS Auto Post have No Author Name, Give A Name */
    	$metadata['author'] = array(
    		'@type' => 'Person',
    		'name' => 'YOUR NAME'
        );
    
       return $metadata; 
    
      } 
    }
    add_filter( 'amp_post_template_metadata', 'amp_modify_json_metadata', 10, 2 ); 
    
    Brendan

Questions and Comments are Welcome

Your email address will not be published. All comments will be moderated.

Please wrap code in "code" bracket tags like this:

[code]

YOUR CODE HERE 

[/code]