Image SEO
File names, alt text that helps both screen readers and search, WebP/AVIF, lazy loading, srcset, image sitemaps, and ranking inside Google Images and Lens.
Images are 50–70% of the bytes on a typical web page and 20%+ of all Google search traffic flows through Google Images and Google Lens. Yet image SEO is treated as an afterthought on most sites — generic file names, missing alt text, oversize JPEGs, and zero structured data. Each one of these is a fixable hole.
TL;DR
- Modern formats are non-negotiable: AVIF first, WebP fallback, JPEG/PNG last. AVIF averages 50% smaller than JPEG at the same quality; WebP is 25–35% smaller. Serving JPEGs in 2026 is leaving Core Web Vitals on the table.
- Alt text is for accessibility first, search second — and the two requirements happen to align. Describe what’s in the image as if to a person who can’t see it. Don’t keyword-stuff. Empty
alt=""is correct for purely decorative images. - Image SEO compounds: file name, alt text, surrounding text, sitemap entry, and structured data all reinforce each other. The image that ranks in Google Images has all five working together.
The mental model
Every image is a triple: the file, the markup, and the context. Search engines and AI crawlers like Googlebot Image see all three as one signal. A great file (high quality, optimized format) with bad markup (no alt text) ranks poorly. Great markup on a generic stock photo (with the wrong filename) ranks poorly. The image that ranks first in Google Images for “Roth IRA contribution limits chart” is named roth-ira-contribution-limits-2026.avif, has alt text “Chart showing 2026 Roth IRA contribution limits by age and income,” sits next to a paragraph about contribution limits, has an ImageObject schema entry, and is in the image sitemap.
Think of each image as a tiny page within your page. It has its own file name (URL), its own description (alt), its own context (surrounding text), and its own discovery channel (image sitemap, structured data). Treat each layer as you would a regular page’s metadata.
Deep dive: the 2026 reality
Google Images and Lens are real traffic. Google reports ~1B Lens visual searches per month as of 2024. Visual search is heavily used in shopping, identification (plants, products, books), and education. Bing Visual Search and Pinterest Lens add meaningful additional volume. For e-commerce sites, image traffic can be 30–50% of total organic traffic.
Format hierarchy.
| Format | Avg savings vs JPEG | Browser support | When to use |
|---|---|---|---|
| AVIF | 50%+ | All modern (2022+) | Always, with fallback |
| WebP | 25–35% | Universal | Fallback when AVIF isn’t generated |
| JPEG | baseline | Universal | Only as last fallback for ancient browsers |
| PNG | larger than JPEG | Universal | Only when transparency is required |
| SVG | tiny | Universal | Logos, icons, line art |
Use the <picture> element to serve AVIF first, WebP second, JPEG last.
Lazy loading. loading="lazy" on <img> is universal and correct in 2026. Apply to all images below the fold; never lazy-load the LCP image (above the fold), which should use fetchpriority="high" instead. Lazy-loading the LCP image will tank your Core Web Vitals (specifically LCP), which is now an Interaction to Next Paint (INP) sibling factor in the Page Experience signal.
srcset and sizes. Every responsive image should serve at least 3–5 widths via srcset with appropriate sizes. The browser picks the right one based on device pixel ratio and viewport. Skipping this serves desktop-resolution images to mobile users and bloats LCP.
File names. IMG_2387.jpg is invisible to search. roth-ira-contribution-limits-2026.avif is descriptive. Hyphens, lowercase, no underscores, no spaces. Match the file name to what’s in the image.
Alt text rules.
| Image type | Alt text approach |
|---|---|
| Informational (chart, screenshot, diagram) | Describe content + key data point |
| Photo with people | Describe who, what, where (if relevant) |
| Product photo | Describe product, color, key feature |
| Decorative (separator, pattern) | alt="" (empty, not missing) |
| Logo (linking to home) | Brand name as alt |
| Icon (UI element with label) | alt="" if label is adjacent |
Length: 50–125 characters is the practical band. Screen readers cut off around 125 in many configurations.
Image sitemaps. A dedicated image sitemap (or images embedded in your URL sitemap) tells Google which images to discover. Critical for sites where images are loaded after first render or hidden behind tabs.
<?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/credit/utilization/</loc>
<image:image>
<image:loc>https://example.com/img/utilization-chart-2026.avif</image:loc>
<image:caption>Credit utilization vs FICO score, 2026 data</image:caption>
</image:image>
</url>
</urlset>
Structured data. Add ImageObject to your Article or Product schema with contentUrl, creator, creditText, copyrightNotice, and license. The 2024 IPTC photo metadata standard expansion gives Google more confidence about image provenance, which has become more important with AI-generated content concerns.
AI Overviews and AI surfaces. AI Overviews displays inline images sourced from cited pages. Perplexity displays images in answer cards. Google Lens results are now shown in AI Mode for visual queries. Pages that earn image citations follow the same rules: descriptive file name, accurate alt, dedicated structured data, and clean source pages with editorial context around each image.
EXIF data. Strip personal EXIF (GPS, device info) on upload for privacy. Keep relevant photo metadata (creator, copyright, caption) for provenance signals.
Visualizing it
flowchart TD
Source["Source image (high quality)"] --> Process["Image pipeline"]
Process --> AVIF["AVIF (50 percent smaller)"]
Process --> WebP["WebP (25-35 percent smaller)"]
Process --> JPEG["JPEG (fallback)"]
Process --> Multi["Multiple widths via srcset"]
Multi --> Markup["picture element with type fallbacks"]
Markup --> Page["Page render"]
Page --> Alt["Descriptive alt text"]
Page --> Schema["ImageObject schema"]
Page --> Sitemap["Entry in image sitemap"]
Alt --> Rank["Ranks in Google Images"]
Schema --> Rank
Sitemap --> Rank
Bad vs. expert
The bad approach
Generic filename, missing alt, single huge JPEG, eager-loaded below the fold.
<img src="/uploads/IMG_2387.jpg" />
<img src="/uploads/IMG_2388.jpg" alt="image" />
<img src="/uploads/IMG_2389.jpg" alt="best credit cards 2026 top credit cards review compare cards" />
<!-- 4MB JPEG below the fold, no lazy load -->
<img src="/uploads/big-banner.jpg" />
The first has no alt and a meaningless filename. The second has an alt of “image,” which is the same as missing for screen readers and search. The third stuffs keywords. The fourth bloats LCP and bandwidth.
The expert approach
<!-- Above the fold (LCP candidate) -->
<picture>
<source
type="image/avif"
srcset="/img/utilization-chart-2026-480.avif 480w,
/img/utilization-chart-2026-768.avif 768w,
/img/utilization-chart-2026-1200.avif 1200w"
sizes="(max-width: 768px) 100vw, 1200px" />
<source
type="image/webp"
srcset="/img/utilization-chart-2026-480.webp 480w,
/img/utilization-chart-2026-768.webp 768w,
/img/utilization-chart-2026-1200.webp 1200w"
sizes="(max-width: 768px) 100vw, 1200px" />
<img
src="/img/utilization-chart-2026-1200.jpg"
width="1200"
height="675"
alt="Chart showing FICO score impact at credit utilization rates from 0 to 100 percent. Score peaks below 10 percent utilization and drops sharply above 30 percent."
fetchpriority="high"
decoding="async" />
</picture>
<!-- Below the fold -->
<picture>
<source type="image/avif" srcset="/img/secured-card-explainer.avif" />
<source type="image/webp" srcset="/img/secured-card-explainer.webp" />
<img
src="/img/secured-card-explainer.jpg"
width="800"
height="450"
alt="Diagram showing how a secured credit card's deposit becomes the credit limit, with arrows from cardholder to issuer"
loading="lazy"
decoding="async" />
</picture>
<!-- Decorative image -->
<img src="/img/divider.svg" alt="" role="presentation" />
{
"@context": "https://schema.org",
"@type": "Article",
"image": [
{
"@type": "ImageObject",
"contentUrl": "https://example.com/img/utilization-chart-2026-1200.avif",
"width": 1200,
"height": 675,
"caption": "FICO score impact by credit utilization rate, 2026 data",
"creator": { "@type": "Person", "name": "Maya Chen" },
"creditText": "Example Personal Finance Editorial",
"copyrightNotice": "Copyright 2026 Example.com",
"license": "https://example.com/licenses/cc-by-4/"
}
]
}
In Astro, use the built-in <Image> component which handles AVIF/WebP fallback automatically:
---
import { Image } from 'astro:assets';
import chart from '../assets/utilization-chart-2026.png';
---
<Image
src={chart}
alt="Chart showing FICO score impact by credit utilization rate"
widths={[480, 768, 1200]}
formats={['avif', 'webp']}
loading="eager"
fetchpriority="high"
/>
In Next.js, the next/image component does the same thing. SvelteKit uses enhanced:img. Remix has third-party adapters.
| Element | Bad | Expert |
|---|---|---|
| Format | Single JPEG | AVIF + WebP + JPEG fallback |
| Filename | IMG_2387.jpg | descriptive-keyword-aware.avif |
| Alt text | Missing or “image” | Descriptive, 50–125 chars |
| Responsive | One size | srcset with 3+ widths |
| Loading | Eager always | Lazy below fold, eager above |
| Schema | None | ImageObject with creator + license |
| Sitemap | URL-sitemap only | Image sitemap entries |
Do this today
- Run PageSpeed Insights at
pagespeed.web.devon your top 5 pages. Check the Opportunities section for “Serve images in next-gen formats” and “Properly size images.” Each is a fix backlog. - Audit images in Screaming Frog > Images tab. Filter by Missing Alt Text, Alt Text Over 100 Characters, and Over 100 KB. Export each list.
- Convert your image pipeline to AVIF + WebP. Tools: Sharp (Node), ImageMagick with
cwebpandcavif-rs, Cloudflare Images, Cloudinary, imgix. If you’re on Astro or Next.js, the built-in image components do this for you. - For each image, write descriptive alt text. Use a quick heuristic: read the alt aloud — would someone who couldn’t see the image understand what’s there? Exclude phrases like “image of” or “picture of.”
- For decorative images (separators, patterns), set
alt=""androle="presentation". Don’t omit the alt attribute entirely — empty alt is the correct accessibility signal. - Rename files in your CMS and uploads to descriptive-hyphenated.avif before you republish. WordPress sites can use the Phoenix Media Rename plugin; static sites can rename in the source.
- Add
widthandheightattributes to every<img>to prevent CLS (Cumulative Layout Shift). Modern browsers reserve the space before the image loads when these are set. - Generate an image sitemap with Screaming Frog > Configuration > XML Sitemaps > Include images, or write one in code. Submit at GSC > Sitemaps.
- For key articles, add
ImageObjectentries to your Article schema withcontentUrl,creator,creditText, andlicense. Validate atvalidator.schema.org. - In Google Search Console > Performance > switch the Search type filter from Web to Image. Track image clicks and impressions monthly. The pages with the most image clicks are candidates for additional images and image-rich rebuilds.
Mark complete
Toggle to remember this module as mastered. Saved to your browser only.
More in this part