Optimizing SEO for Images (Image Sitemap, Lazy Loading SEO)
Images are the second-largest organic traffic source after text results for many sites. E-commerce, portfolios, news sites with photos get significant traffic via Google Images. Without proper optimization this channel is closed: missing alt texts, improper lazy loading, missed image sitemap — search engines can't properly process content.
Alt Text: Minimum and Maximum
Alt is the primary signal for Google Images. Rules:
- Describes content, not keywords
- Decorative images:
alt=""(empty, not absent) - Images as links: describes purpose, not image itself
- Length: up to 125 characters practically
<!-- Bad: keyword stuffing -->
<img src="laptop.jpg" alt="notebook buy cheap notebook apple">
<!-- Bad: empty where needed -->
<img src="laptop-product-photo.jpg" alt="">
<!-- Good -->
<img src="macbook-pro-m3-space-gray.jpg" alt="MacBook Pro M3 14 inches, Space Gray, front view">
<!-- Decorative -->
<img src="divider.svg" alt="" role="presentation">
Image Sitemap
Image Sitemap lets Google discover images it might miss — especially if loaded via JavaScript.
<?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/products/macbook-pro-m3/</loc>
<image:image>
<image:loc>https://cdn.example.com/products/macbook-pro-m3-front.webp</image:loc>
<image:title>MacBook Pro M3 — front view</image:title>
<image:caption>MacBook Pro with M3, 14 inches, Space Gray</image:caption>
</image:image>
</url>
</urlset>
Up to 1000 images per <url>. For large catalogs — Sitemap Index.
Lazy Loading: Proper Implementation
loading="lazy" — native attribute, browsers and Googlebot understand since 2019. Problem: historically many sites implemented via data-src and JavaScript — such images Google may not discover.
Native lazy loading (recommended):
<!-- Above fold: no lazy, with fetchpriority -->
<img
src="/hero.webp"
width="1200"
height="800"
fetchpriority="high"
alt="..."
/>
<!-- Below fold: lazy loading -->
<img
src="/product-1.webp"
width="400"
height="300"
loading="lazy"
alt="..."
/>
JavaScript via Intersection Observer (for old browser support):
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
if (img.dataset.srcset) {
img.srcset = img.dataset.srcset;
}
observer.unobserve(img);
}
});
}, {
rootMargin: '200px 0px'
});
document.querySelectorAll('img.lazy').forEach(img => {
imageObserver.observe(img);
});
SEO issue: Googlebot sees src="/placeholder.svg" and data-src="/product-1.webp". Google can process data-src pattern, but native loading="lazy" is more reliable.
Check: GSC → URL Inspection → View Crawled Page → Screenshots. If images empty — Googlebot can't see content.
Formats and Sizes
WebP with JPEG/PNG fallback:
<picture>
<source
srcset="/product.webp 1x, /[email protected] 2x"
type="image/webp"
/>
<img
src="/product.jpg"
srcset="/product.jpg 1x, /[email protected] 2x"
loading="lazy"
alt="..."
/>
</picture>
AVIF for modern browsers:
<picture>
<source srcset="/product.avif" type="image/avif" />
<source srcset="/product.webp" type="image/webp" />
<img src="/product.jpg" loading="lazy" alt="..." />
</picture>
AVIF reduces size 50–60% vs JPEG at same quality. Support: Chrome 85+, Firefox 93+, Safari 16+.
Responsive images:
<img
srcset="
/product-320w.webp 320w,
/product-640w.webp 640w,
/product-1280w.webp 1280w
"
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
src="/product-640w.webp"
loading="lazy"
alt="..."
/>
Without width and height browser can't reserve space — CLS grows, Core Web Vitals worsen.
File Names and CDN
Filename is weak but considered signal:
# Bad
IMG_20241015_143022.jpg
photo_2024_10_15.webp
# Good
macbook-pro-m3-14-space-gray.webp
samsung-galaxy-s24-ultra-titanium-black.webp
If images on CDN with hashed names — not critical, but alt and caption compensate.
Cache-Control for images:
location ~* \.(webp|avif|jpg|jpeg|png|gif|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
Audit Current State
# Find images without alt via Screaming Frog
# Reports → Images → Missing Alt Text
# Via puppeteer (for JS-rendered sites)
node -e "
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
const missingAlts = await page.evaluate(() =>
[...document.images].filter(img => !img.alt).map(img => img.src)
);
console.log('Missing alt:', missingAlts);
await browser.close();
})();
"
GSC Enhancement → Images: Google reports pages where images can't be indexed.
Timeline
Image audit (alt, formats, lazy loading) on 100-page site — 1–2 days. Image Sitemap + auto-generation — 2–3 days. Convert existing images to WebP/AVIF — depends on volume; batch conversion script + template updates — 2–4 days.







