Schema images are what Google uses for rich result thumbnails, news carousels, recipe cards, and the visual element of most enhanced search features. Get them wrong and your content shows without a thumbnail — losing click-through to competitors who got it right. Errors typically cluster around: bare URLs instead of ImageObject, missing dimensions, relative paths, and images too small for Google's minimums. This guide covers the format, requirements, and tooling for getting it right consistently.
{
"@type": "Article",
"image": "https://yoursite.com/article-hero.jpg"
}
Works for basic structured data. Doesn't qualify for Article rich results, which need explicit dimensions.
{
"@type": "Article",
"image": {
"@type": "ImageObject",
"url": "https://yoursite.com/article-hero.jpg",
"width": 1200,
"height": 675,
"caption": "Optional caption text"
}
}
{
"@type": "Article",
"image": [
{
"@type": "ImageObject",
"url": "https://yoursite.com/article-hero-16x9.jpg",
"width": 1200,
"height": 675
},
{
"@type": "ImageObject",
"url": "https://yoursite.com/article-hero-4x3.jpg",
"width": 1200,
"height": 900
},
{
"@type": "ImageObject",
"url": "https://yoursite.com/article-hero-1x1.jpg",
"width": 1200,
"height": 1200
}
]
}
Google picks the right aspect ratio for each surface. Article rich results in different layouts use different ratios; providing all three maximises placement.
// WRONG "url": "/images/article-hero.jpg" "url": "//cdn.example.com/image.jpg" // protocol-relative also fails // RIGHT "url": "https://yoursite.com/images/article-hero.jpg" "url": "https://cdn.example.com/image.jpg"
In templates, prepend the canonical domain:
// WordPress
"url": "<?php echo esc_url(get_the_post_thumbnail_url($post, 'large')); ?>"
// Next.js
"url": `https://yoursite.com${image.url}`
Google needs to fetch the image. Common reasons fetching fails:
# Verify Googlebot can fetch
curl -A "Mozilla/5.0 (compatible; Googlebot/2.1)" \
-I https://yoursite.com/images/article-hero.jpg
# Expect: 200 OK, Content-Type: image/...
Organization.logo has stricter requirements than article images:
{
"@type": "Organization",
"@id": "https://yoursite.com/#organization",
"name": "Acme Co",
"url": "https://yoursite.com",
"logo": {
"@type": "ImageObject",
"url": "https://yoursite.com/logo.png",
"width": 600,
"height": 60
}
}
$thumb_id = get_post_thumbnail_id($post); $meta = wp_get_attachment_metadata($thumb_id); $url = wp_get_attachment_url($thumb_id); $image_object = [ '@type' => 'ImageObject', 'url' => $url, 'width' => $meta['width'], 'height' => $meta['height'] ];
import sharp from 'sharp';
async function getImageDimensions(filePath) {
const meta = await sharp(filePath).metadata();
return { width: meta.width, height: meta.height };
}
// At build or request time
const { width, height } = await getImageDimensions(article.imagePath);
const imageObject = {
'@type': 'ImageObject',
url: `https://yoursite.com${article.image}`,
width,
height
};