39 patterns in this category — each with its illustration, what it is, and the fields that matter when you build or review one. Part of the UX pattern catalogue; the raw, agent-readable version is ux-pattern-catalogue/seo-patterns.json.
Technical
Canonical URL Tag seo-001
A <link rel="canonical"> tag on every page that tells search engines and AI agents which URL is the authoritative version of that content. Self-referencing on unique pages, cross-domain for syndicated or republished content. Prevents duplicate content penalties when the same page is accessible via multiple URLs (www vs non-www, HTTP vs HTTPS, trailing slashes, query parameters).
Implementation
Add <link rel="canonical" href="{absolute-url}"> in <head> on every page. Use the full absolute URL including protocol. For paginated content, each page gets its own canonical (not all pointing to page 1). For syndicated content, point canonical to the original source. Ensure canonical URL matches the URL in the sitemap. Trailing slash consistency: pick one and enforce everywhere. Dynamic pages: generate canonical from the clean URL, stripping tracking parameters (utm_*, fbclid, etc.).
Accessibility
Canonical tags are invisible metadata. No accessibility impact. They exist purely for search engine and AI agent consumption.
An auto-generated XML sitemap listing all indexable pages with their last modification date, change frequency, and priority. Registered in robots.txt so crawlers find it automatically. Split into sub-sitemaps at 50,000 URLs. Helps search engines discover and prioritize pages, especially for large sites or pages not well-linked internally.
Implementation
Generate at build time. Include only canonical, indexable URLs (no noindex pages, no redirects, no error pages). Set <lastmod> from the file's actual last modification date (git commit date or CMS modified timestamp). <changefreq> and <priority> are advisory but use them consistently: homepage priority="1.0", key landing pages priority="0.8", blog posts priority="0.6". Register in robots.txt: Sitemap: https://example.com/sitemap.xml. For large sites, create a sitemap index file pointing to sub-sitemaps of 50k URLs max.
Accessibility
XML sitemaps are machine-readable files. No user-facing component and no accessibility impact.
A plain text file at the site root that controls which crawlers can access which parts of the site. Blocks admin pages, API endpoints, search result pages, and paginated archives from indexing. Includes the sitemap URL directive. Provides separate directives for AI crawlers (GPTBot, ClaudeBot, etc.) to control what AI models can access.
Implementation
Place at /robots.txt (must be at root). Default: User-agent: * Allow: /. Block utility paths: Disallow: /api/, /admin/, /search?, /_next/. Add sitemap: Sitemap: https://example.com/sitemap.xml. For AI crawlers, add specific sections: User-agent: GPTBot Allow: / and User-agent: ClaudeBot Allow: /. Test with Google Search Console's robots.txt tester. Keep rules simple -- complex wildcards are error-prone. Never block CSS/JS files that search engines need to render pages.
Accessibility
robots.txt is a machine-readable file. No user-facing component and no accessibility impact.
Clean, descriptive, hierarchical URLs that reflect the site structure. Uses /docs/getting-started not /page?id=42. Breadcrumb-aligned so the URL path matches the navigation hierarchy. Combined with 301 redirects for any changed URLs to preserve link equity and avoid broken links.
Implementation
Use lowercase, hyphen-separated words: /blog/my-post-title. Keep URLs short (3-5 segments max). Avoid: IDs, query strings for content, file extensions (.html), underscores, uppercase. URL segments should match breadcrumb levels: /docs/guides/setup maps to Docs > Guides > Setup. Implement 301 redirects when URLs change (never 302 for permanent moves). Trailing slash: pick a convention (with or without) and redirect the other. For dynamic routes, generate slugs from titles at creation time.
Accessibility
Clean URLs benefit all users by being readable, memorable, and shareable. Screen readers announce URLs -- descriptive paths are easier to understand than opaque IDs.
Meta
Open Graph Tags seo-005
Open Graph meta tags that control how pages appear when shared on social platforms, messaging apps, and link previews. Every page needs og:title, og:description, og:image, og:url, og:type, and og:site_name. The OG image is the single most impactful tag -- a compelling 1200x630px image dramatically increases click-through rates on shared links.
Implementation
Add to <head>: <meta property="og:title" content="{title}">, <meta property="og:description" content="{description}">, <meta property="og:image" content="{absolute-image-url}">, <meta property="og:url" content="{canonical-url}">, <meta property="og:type" content="website"> (or "article" for blog posts), <meta property="og:site_name" content="{Site Name}">. Image requirements: 1200x630px minimum, absolute URL, HTTPS. Every page gets unique OG tags -- never share the same title/description across pages. Fallback: set site-wide defaults that individual pages override.
Accessibility
OG tags are invisible metadata. No accessibility impact. They only affect how the page appears when shared externally.
Twitter Card meta tags that control how links appear in Twitter/X posts and DMs. While Twitter falls back to OG tags, explicit Twitter Card tags give finer control. The summary_large_image card type displays the largest preview image and consistently gets higher engagement than summary cards.
Implementation
Add to <head>: <meta name="twitter:card" content="summary_large_image">, <meta name="twitter:title" content="{title}">, <meta name="twitter:description" content="{description}">, <meta name="twitter:image" content="{image-url}">, <meta name="twitter:site" content="@{handle}">. If OG tags are already set, you can omit twitter:title and twitter:description (Twitter falls back to OG). But always set twitter:card (no OG equivalent) and twitter:image (can differ from og:image for aspect ratio optimization). Validate with Twitter Card Validator before launching.
Accessibility
Twitter Card tags are invisible metadata. No accessibility impact.
A unique 150-160 character description for each page that appears in search engine result snippets. Not a direct ranking factor, but strongly influences click-through rate. Action-oriented for landing pages ("Start building in minutes"), content-summarizing for articles ("Learn how to implement OAuth 2.0 with PKCE in a React SPA").
Implementation
Add <meta name="description" content="{description}"> to <head>. Keep between 150-160 characters (Google truncates around 155-160). Make each description unique -- never duplicate across pages. Include the primary keyword naturally. For landing pages: lead with a benefit or call to action. For articles: summarize the key takeaway. For product pages: highlight the main value proposition. Never keyword-stuff. Generate programmatically from content excerpts where possible, with manual overrides for key pages.
Accessibility
Meta descriptions are invisible metadata. No accessibility impact. Screen readers do not read meta descriptions -- they read page content.
Per-page robots directives that control whether search engines index a page and follow its links. Used to prevent indexing of utility pages (search results, pagination, admin panels, login pages) that would dilute search quality. The default is index, follow -- only add noindex for pages that should not appear in search results.
Implementation
Add <meta name="robots" content="{directives}"> to <head>. Common directives: index, follow (default -- can be omitted), noindex (exclude from search results), nofollow (don't follow links on this page), noarchive (no cached copy). Apply noindex to: search result pages, paginated archives beyond page 1, login/register pages, admin pages, user-specific dashboards, thank-you/confirmation pages, URL parameter variations. Never noindex your homepage or key landing pages. For sections: use robots.txt to block crawling entirely (saves crawl budget).
Accessibility
Meta robots are invisible metadata. No accessibility impact.
Multi-size favicons and a web app manifest that establish brand identity across browser tabs, bookmarks, home screens, and app stores. Modern browsers support SVG favicons for crisp rendering at any size. The manifest enables "Add to Home Screen" and provides app metadata for search engines.
Implementation
Provide favicons at key sizes: <link rel="icon" type="image/svg+xml" href="/favicon.svg"> (modern browsers), <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"> (fallback), <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"> (iOS). Create manifest.json: { "name": "{App}", "short_name": "{App}", "icons": [{src, sizes, type}], "theme_color": "#...", "background_color": "#...", "display": "standalone" }. Link it: <link rel="manifest" href="/manifest.json">. Include 192x192 and 512x512 PNG icons in the manifest for PWA support.
Accessibility
Favicons are visual brand indicators. No direct accessibility impact, but they help all users identify tabs. The manifest's theme_color should have sufficient contrast with white text for address bar readability.
Site-level JSON-LD structured data using the Schema.org WebSite type. Placed on the homepage, it tells search engines and AI agents the site name, URL, and description. Including a SearchAction enables the sitelinks search box in Google results -- a prominent feature that lets users search your site directly from the SERP.
Implementation
Add to homepage <head>: <script type="application/ld+json">{"@context":"https://schema.org","@type":"WebSite","name":"{Site Name}","url":"https://example.com","description":"{description}","potentialAction":{"@type":"SearchAction","target":"https://example.com/search?q={search_term_string}","query-input":"required name=search_term_string"}}</script>. Only include SearchAction if you have a functional site search. Validate with Google Rich Results Test. Include the publisher (Organization) if applicable.
Accessibility
JSON-LD is invisible to users and screen readers. It is purely machine-readable metadata in a <script> tag.
JSON-LD breadcrumb structured data on every interior page that matches the visible breadcrumb UI. Enhances search result display with a breadcrumb trail instead of the raw URL. Helps search engines understand site hierarchy and improves click-through rates by showing the content path.
Implementation
Add JSON-LD on every interior page: {"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://example.com"},{"@type":"ListItem","position":2,"name":"Docs","item":"https://example.com/docs"},{"@type":"ListItem","position":3,"name":"Setup"}]}. The last item (current page) omits the "item" URL. Position starts at 1. Names should match the visible breadcrumb text. Generate automatically from the URL structure or navigation data.
Accessibility
JSON-LD breadcrumbs are invisible metadata. The visible breadcrumb UI should use <nav aria-label="Breadcrumb"> with an <ol> for proper screen reader support -- the structured data is a separate concern.
JSON-LD Article or TechArticle structured data for blog posts and documentation pages. Enables rich snippets in search results with headline, author, publish date, and image. The dateModified field is particularly valuable -- it signals content freshness to search engines and AI agents, which both prefer up-to-date content.
Implementation
Add to blog/doc pages: {"@context":"https://schema.org","@type":"TechArticle","headline":"{title}","datePublished":"{ISO-date}","dateModified":"{ISO-date}","author":{"@type":"Person","name":"{name}","url":"{profile-url}"},"publisher":{"@type":"Organization","name":"{org}","logo":{"@type":"ImageObject","url":"{logo-url}"}},"image":"{featured-image-url}","description":"{excerpt}"}. Use TechArticle for technical docs, Article for general blog posts. dateModified should reflect actual content changes (not redeploys). Generate from git commit dates or CMS timestamps.
Accessibility
JSON-LD Article schema is invisible metadata. The visible article should use semantic HTML: <article>, <header>, <time datetime="...">, <address> for author.
JSON-LD SoftwareApplication structured data for product and download pages. Enables software rich snippets in search results showing the app name, category, operating system, price, and rating. Particularly valuable for developer tools, SaaS products, and open-source projects.
Implementation
Add to product/landing page: {"@context":"https://schema.org","@type":"SoftwareApplication","name":"{App Name}","applicationCategory":"DeveloperApplication","operatingSystem":"Any","offers":{"@type":"Offer","price":"0","priceCurrency":"USD"},"description":"{description}","url":"{landing-page-url}"}. For paid software, set the correct price. For freemium, use the free tier price. Add aggregateRating if you have verified ratings. applicationCategory values: DeveloperApplication, BusinessApplication, WebApplication, etc. Validate with Google Rich Results Test.
Accessibility
JSON-LD is invisible metadata. No accessibility impact.
JSON-LD Product structured data for pricing pages, product listings, and e-commerce. Enables rich results showing price, currency, availability, review ratings, and seller info directly in the SERP. One of the highest-impact schema types -- product rich results have significantly higher click-through rates than plain blue links.
Implementation
Add to product/pricing pages: {"@context":"https://schema.org","@type":"Product","name":"{Product Name}","description":"{description}","image":"{image-url}","brand":{"@type":"Organization","name":"{Brand}"},"offers":{"@type":"Offer","price":"{price}","priceCurrency":"USD","availability":"https://schema.org/InStock","url":"{page-url}"}}. For multiple pricing tiers, use AggregateOffer with lowPrice and highPrice. Add aggregateRating with ratingValue and reviewCount if you have verified reviews. For SaaS: use "0" price for free tiers, actual price for paid. Availability values: InStock, OutOfStock, PreOrder, Discontinued. Validate with Google Rich Results Test.
Accessibility
JSON-LD is invisible metadata. No accessibility impact. The visible pricing page should use semantic HTML with clear price labels and ARIA attributes on interactive elements (plan selectors, CTAs).
JSON-LD Organization structured data that establishes your brand identity in search. Enables the Google Knowledge Panel (the sidebar card showing your logo, description, social links, and contact info). Placed on the homepage and about page. The sameAs property connects your site to official social profiles, which Google uses to verify and display your brand information.
Implementation
Add to homepage and about page: {"@context":"https://schema.org","@type":"Organization","name":"{Company}","url":"https://example.com","logo":"https://example.com/logo.png","description":"{description}","sameAs":["https://twitter.com/{handle}","https://github.com/{org}","https://linkedin.com/company/{slug}"],"contactPoint":{"@type":"ContactPoint","contactType":"customer support","email":"{email}"}}. Logo: square, at least 112x112px, light background. sameAs: list all official social profile URLs. For startups: include foundingDate, founders, and numberOfEmployees if public. Validate with Google Rich Results Test.
Accessibility
JSON-LD is invisible metadata. No accessibility impact.
JSON-LD VideoObject structured data for pages containing video content (demos, tutorials, webinars). Enables video rich results in Google with thumbnail, duration, upload date, and play button overlay. Videos with structured data can also appear in Google Video search and the video carousel. Particularly valuable for product demos and tutorial content.
Implementation
Add to pages with video: {"@context":"https://schema.org","@type":"VideoObject","name":"{title}","description":"{description}","thumbnailUrl":"https://example.com/thumb.jpg","uploadDate":"{ISO-date}","duration":"PT{X}M{Y}S","contentUrl":"https://example.com/video.mp4","embedUrl":"https://www.youtube.com/embed/{id}"}. Duration uses ISO 8601 format (PT5M30S = 5 min 30 sec). thumbnailUrl: 16:9 aspect ratio, minimum 120x120px. For YouTube/Vimeo embeds, provide the embed URL. Add transcript text in the description or as a separate property for AI discoverability. Validate with Google Rich Results Test.
Accessibility
JSON-LD is invisible metadata. The visible video player must have captions/subtitles (WCAG 1.2.2), a text transcript (WCAG 1.2.1), and keyboard-accessible controls. Never autoplay with sound.
JSON-LD Event structured data for webinars, conferences, launches, meetups, and workshops. Enables event rich results in Google showing the event name, date, location (physical or online), and ticket/registration info. Online events use VirtualLocation with a URL. Events appear in Google Search and Google Events, significantly expanding discoverability beyond your site.
Implementation
Add to event pages: {"@context":"https://schema.org","@type":"Event","name":"{Event Name}","startDate":"{ISO-datetime}","endDate":"{ISO-datetime}","eventAttendanceMode":"https://schema.org/OnlineEventAttendanceMode","eventStatus":"https://schema.org/EventScheduled","location":{"@type":"VirtualLocation","url":"https://example.com/join"},"description":"{description}","organizer":{"@type":"Organization","name":"{org}","url":"https://example.com"},"offers":{"@type":"Offer","price":"0","priceCurrency":"USD","availability":"https://schema.org/InStock","url":"{registration-url}"}}. For in-person: use Place with address. For hybrid: use MixedEventAttendanceMode. Update eventStatus if cancelled (EventCancelled) or rescheduled (EventRescheduled). Validate with Google Rich Results Test.
Accessibility
JSON-LD is invisible metadata. The visible event page should clearly present date, time (with timezone), location, and registration in accessible, semantic HTML.
JSON-LD FAQPage structured data for pages with question-and-answer content. Enables FAQ rich results in Google -- expandable Q&A pairs directly in the search results that dramatically increase SERP real estate and click-through rates. Works for dedicated FAQ pages and for any page with an expandable Q&A section.
Implementation
Add to pages with Q&A content: {"@context":"https://schema.org","@type":"FAQPage","mainEntity":[{"@type":"Question","name":"{question}","acceptedAnswer":{"@type":"Answer","text":"{answer}"}}]}. Each question-answer pair is a mainEntity item. The answer text can include HTML (links, lists). Limit to 10-15 questions per page for best results. Questions should match the visible page content exactly. Do not mark up content that is not visually present as Q&A. Google may show 2-4 FAQ results for your page.
Accessibility
JSON-LD FAQ schema is invisible metadata. The visible FAQ section should use proper disclosure/accordion patterns: <details>/<summary> or buttons with aria-expanded.
JSON-LD HowTo structured data for tutorial and step-by-step guide pages. Enables how-to rich results in Google with step previews, images, and time estimates. Ideal for setup guides, getting-started tutorials, and recipe-style content where the content naturally follows sequential steps.
Implementation
Add to tutorial/guide pages: {"@context":"https://schema.org","@type":"HowTo","name":"{title}","description":"{summary}","step":[{"@type":"HowToStep","name":"{step title}","text":"{step description}","image":"{step-image-url}","url":"{page-url}#step-1"}]}. Include estimatedCost and totalTime if applicable. Each step's url should deep-link to the corresponding section on the page using anchor IDs. Steps should match the visible content. Add tool and supply items if the guide requires specific prerequisites.
Accessibility
JSON-LD HowTo is invisible metadata. The visible tutorial should use an <ol> (ordered list) for sequential steps, with descriptive headings for each step.
A root-level /llms.txt file following the llmstxt.org specification. It is the first file AI agents and LLM-powered tools look for when trying to understand a website. Contains a concise markdown summary: project name, what it does, key capabilities, and links to important pages. Think of it as robots.txt for AI agents -- a machine-readable site introduction.
Implementation
Create a plain text file at /llms.txt (public root). Format as markdown following the spec: start with # {Project Name}, then a one-paragraph description, then ## Key Links with the most important pages (docs, API reference, getting started). Keep it concise -- under 500 lines. Focus on what an AI agent needs to answer user questions about your product. Update on each deploy. Include version/date. Link to llms-full.txt for comprehensive content. Do not include marketing fluff -- AI agents need facts.
Accessibility
llms.txt is a machine-readable file. No user-facing component and no accessibility impact.
A comprehensive /llms-full.txt file that flattens all documentation into a single markdown document. Enables full-context ingestion by AI models that support large context windows. Auto-generated at build time by concatenating and converting all documentation pages. The counterpart to the concise llms.txt -- where llms.txt is the summary, llms-full.txt is the complete reference.
Implementation
Build script: iterate all documentation pages, convert HTML to markdown (using a library like turndown or html-to-text), concatenate with ## headers separating pages. Include a table of contents at the top. Strip navigation chrome, sidebars, and repeated elements (headers/footers). Order pages logically (getting started first, reference last). Keep under 100k tokens if possible (most LLMs handle this well). Regenerate on every build. Add a generation timestamp at the top.
Accessibility
llms-full.txt is a machine-readable file. No user-facing component and no accessibility impact.
Content organized for optimal extraction by AI agents: clear heading hierarchy (single H1, logical H2-H4), summary or TLDR at the top of long pages, code blocks with language tags, tables for structured comparisons instead of prose. AI agents parse content by headings and code blocks -- well-structured pages get more accurate citations and answers.
Implementation
Every page: single <h1> matching the title, logical <h2>-<h4> nesting with no skipped levels. Long pages (>1000 words): add a TLDR or summary section after the H1. Code blocks: always include the language tag (```typescript, ```bash). Data comparisons: use tables instead of bullet lists when comparing features, options, or configurations. Definitions: use <dl>/<dt>/<dd> for glossary-style content. Anchor IDs on all headings for deep linking. Key facts in the first paragraph (inverted pyramid structure).
Accessibility
AI-friendly structure is also accessibility-friendly. Clear heading hierarchy is a WCAG 2.1 requirement. Proper code blocks, tables, and definition lists all improve screen reader navigation. This pattern is a convergence of SEO, AI, and accessibility best practices.
robots.txt AI Bot Directives seo-023
Explicit allow/disallow rules in robots.txt for known AI crawler user agents: GPTBot (OpenAI), ClaudeBot (Anthropic), Applebot-Extended (Apple Intelligence), Google-Extended (Gemini training), Bytespider (TikTok), CCBot (Common Crawl). Gives site owners granular control over which AI models can access their content for training versus inference.
Implementation
Add separate User-agent blocks for each AI bot: User-agent: GPTBot / Allow: /docs/ / Disallow: /api/. Common AI bots to configure: GPTBot, ChatGPT-User, ClaudeBot, Google-Extended, Applebot-Extended, Bytespider, CCBot, PerplexityBot, cohere-ai. Distinguish between training bots (Google-Extended trains Gemini) and inference bots (ChatGPT-User serves live answers). Allow inference bots for discoverability, consider blocking training bots if you want to protect content from model training. Test that bots respect your rules by monitoring access logs.
Accessibility
robots.txt is a machine-readable file. No user-facing component and no accessibility impact.
HTML landmark elements (<article>, <nav>, <main>, <aside>, <header>, <footer>) and semantic tags (<time datetime>, <code>, <abbr>, <cite>) that help AI agents extract structured information from pages. AI models use these landmarks to identify the main content versus navigation, sidebars, and boilerplate. Pages with strong semantic HTML get more precise AI-generated answers.
Implementation
Every page: <main> wrapping the primary content, <header> for site header, <footer> for site footer, <nav> for navigation sections. Content pages: <article> wrapping each distinct piece of content. Sidebar: <aside>. Dates: <time datetime="2024-01-15">January 15, 2024</time>. Code: <code> for inline, <pre><code> for blocks. Abbreviations: <abbr title="Search Engine Optimization">SEO</abbr>. Citations: <cite>. Do not use <div> and <span> where a semantic element exists. These landmarks also directly improve screen reader navigation.
Accessibility
Semantic HTML is the foundation of web accessibility. <main>, <nav>, <header>, <footer> create landmark regions that screen readers use for navigation. <time> provides machine-readable dates. This pattern is equally an accessibility pattern and an AI discoverability pattern.
A single <h1> per page matching the title tag, with logical <h2> through <h4> nesting and no skipped levels. Headings describe content, not style -- "Getting Started" not "Big Blue Text". Search engines weight heading content heavily for relevance. Screen readers and AI agents both navigate by heading structure, making this a convergence point of SEO, accessibility, and AI discoverability.
Implementation
One <h1> per page, matching (or closely matching) the <title> tag content. <h2> for major sections, <h3> for subsections, <h4> for sub-subsections. Never skip levels (h2 directly to h4). Never use headings for styling -- use CSS classes instead. Keep headings concise and descriptive. Include relevant keywords naturally (not forced). For SPA/dynamic content: ensure the heading hierarchy is correct in the rendered DOM, not just the source template.
Accessibility
Heading hierarchy is a WCAG 2.1 Level A requirement (1.3.1 Info and Relationships). Screen reader users navigate by headings (the "H" shortcut). Skipped levels create confusing navigation. Single H1 clearly identifies the page topic. This is non-negotiable for accessible content.
Internal Linking Strategy seo-026
Contextual links between related pages in a hub-and-spoke topology. Pillar pages (hubs) link to detailed pages (spokes) and vice versa. Descriptive anchor text ("OAuth 2.0 implementation guide" not "click here") helps both crawlers and AI agents understand content relationships. Strong internal linking distributes page authority and keeps users engaged longer.
Implementation
Every page should link to 3-5 related pages within the body content (not just navigation). Use descriptive anchor text that describes the destination. Hub pages (guides, overviews) link to all related detail pages. Detail pages link back to their hub and to sibling pages. Avoid orphan pages (pages with no internal links pointing to them). Add "Related pages" sections at the bottom of articles. For large sites, use a topic cluster model: one pillar page per major topic with spoke pages for subtopics.
Accessibility
Descriptive anchor text is a WCAG 2.1 Level A requirement (2.4.4 Link Purpose). "Click here" and "read more" are inaccessible -- screen reader users often navigate by link list and need descriptive text. This SEO best practice is also an accessibility requirement.
Image SEO seo-027
Descriptive alt text, lazy loading for below-fold images, explicit width/height attributes for CLS prevention, modern formats (WebP/AVIF), and descriptive filenames. Images are a major search traffic source via Google Images. Proper image SEO also directly supports accessibility (alt text) and performance (lazy loading, compression).
Implementation
Alt text: describe the image content and function, not "image of..." (e.g., "Dashboard showing real-time analytics with 3 charts"). Filenames: use descriptive names (analytics-dashboard.webp not IMG_4523.webp). Dimensions: always include width and height attributes to prevent CLS. Loading: loading="lazy" on all images below the fold, eager (default) for above-fold hero images. Format: serve WebP or AVIF with <picture> fallback to JPEG/PNG. Use srcset and sizes for responsive images. Compress aggressively (quality 80 for photos).
Accessibility
Alt text is a WCAG 2.1 Level A requirement (1.1.1 Non-text Content). Every informative <img> must have descriptive alt text. Decorative images: alt="". Charts/diagrams: provide a text description or data table alternative. This is the strongest convergence of SEO and accessibility.
Anchor-Based Deep Linking seo-028
Meaningful id attributes on sections, patterns, and key content blocks that enable direct linking to specific content. AI agents and search engines can reference specific sections of a page. Users can share links to exact content. Combined with a visible anchor link icon on hover, this encourages citation and improves the granularity of search results.
Implementation
Add id attributes to all <h2>, <h3>, and <h4> headings: <h2 id="getting-started">. Generate IDs from heading text (lowercase, hyphenated). Show a hover-visible link icon (# or chain icon) next to headings that copies or navigates to the anchor URL. Ensure IDs are unique within the page. For pattern pages or reference content, add IDs to individual items (not just headings). Use the anchor in BreadcrumbList and HowTo schema URLs for deep linking from structured data.
Accessibility
Anchor links improve navigation for all users. The hover link icon should be keyboard-accessible (visible on focus, not just hover). Anchor IDs should not conflict with ARIA IDs. Skip link (#main-content) is a related accessibility pattern.
Sharing
OG Image Generation seo-029
Dynamic or template-based OG images generated per page so every shared link has a unique, branded preview image. The OG image is the highest-impact meta tag for social sharing -- posts with custom images get 2-3x more engagement than those with generic or missing previews. Template-based generation ensures consistency while scaling to hundreds of pages.
Implementation
Option A (build-time): Use satori (@vercel/og) to generate images from an HTML/CSS template at build time. Template: page title in large text, site logo, brand colors, optional category tag. Output: 1200x630px PNG. Generate one per page and reference the static file in og:image. Option B (static): design a reusable template in Figma, export variants for key pages, use a single default for others. Always use absolute HTTPS URLs for og:image. Test with Facebook Sharing Debugger and Twitter Card Validator.
Accessibility
OG images are only displayed on external platforms (social media, messaging). They have no direct accessibility impact on your site. However, the og:image alt text equivalent is the og:title and og:description -- ensure those are descriptive.
Share URL Hygiene seo-030
Clean canonical URLs in all share metadata, free of tracking parameters, session IDs, and internal state. UTM parameters for campaign tracking are added client-side at the moment of sharing, never baked into the canonical URL or OG tags. Ensures consistent URL identity across shares and prevents duplicate content from parameter variations.
Implementation
Canonical URL and og:url must always be the clean URL (no query parameters). When generating share links (Static Share Links pattern), use the canonical URL as the base. Add UTM parameters client-side: ?utm_source={platform}&utm_medium=social&utm_campaign={campaign}. Strip existing tracking params (fbclid, gclid, mc_cid) before constructing share URLs. Never include session IDs, auth tokens, or user-specific parameters in share URLs. Test: shared URL should resolve to the same content for any user.
Accessibility
Share URL hygiene has no direct accessibility impact. It is a data cleanliness concern for analytics and SEO.
Rich Link Preview Testing seo-031
Systematic validation that OG tags and Twitter Cards render correctly across platforms before publishing. Uses platform debugger tools to preview exactly how shared links will appear. Catches missing images, truncated titles, wrong descriptions, and broken URLs before they reach your audience. Should be part of the pre-launch and content publishing checklist.
Implementation
Test with: Facebook Sharing Debugger (developers.facebook.com/tools/debug/), Twitter Card Validator (cards-dev.twitter.com/validator), LinkedIn Post Inspector (linkedin.com/post-inspector/). Clear platform caches after updating OG tags (Facebook: "Scrape Again" button). Automate: add OG tag validation to your CI pipeline (validate required properties exist, image URL resolves, dimensions are correct). For content sites: test a sample page from each template type. Common issues: relative image URLs (must be absolute), HTTP images (must be HTTPS), images too small (<200px).
Accessibility
Link preview testing has no direct accessibility impact on your site. It ensures shared content is presented correctly on external platforms.
Monitoring
Structured Data Validation seo-032
Automated testing of JSON-LD structured data at build time to catch syntax errors, missing required properties, and deprecated schema types before they reach production. Invalid structured data silently fails -- search engines ignore it without warning, and you lose rich results until someone manually checks. Build-time validation makes this a non-issue.
Implementation
Add to CI pipeline: parse all JSON-LD blocks, validate syntax (valid JSON), validate against Schema.org types (required properties present, correct types). Use Google Rich Results Test API for automated validation. Check: no duplicate schema types on the same page, all URLs are absolute HTTPS, dates are ISO 8601 format, image URLs resolve. For development: add a browser extension or dev-mode overlay that highlights JSON-LD on the page. Run schema validation as a build step that fails on errors.
Accessibility
Structured data validation is a build/CI concern. No direct accessibility impact, but some schema types (FAQ, HowTo) should have corresponding accessible visible content.
Google Search Console verification and ongoing monitoring for indexing status, coverage errors, Core Web Vitals, and search performance data. The primary feedback loop for understanding how Google sees your site. Alerts you to crawl errors, security issues, manual actions, and indexing problems before they impact traffic.
Implementation
Verify ownership via meta tag (<meta name="google-site-verification" content="{code}">) or DNS TXT record. Submit your sitemap. Monitor weekly: Index Coverage (errors, excluded pages, valid pages), Performance (impressions, clicks, CTR, average position), Core Web Vitals (LCP, INP, CLS), and Enhancements (structured data errors). Set up email alerts for critical issues. Fix crawl errors promptly (404s, server errors, redirect loops). Use the URL Inspection tool to debug individual page indexing. For multi-site: use Bing Webmaster Tools as a secondary signal.
Accessibility
Search Console is an external monitoring tool. No direct accessibility impact on your site.
HTML pages are the entry point to your site and cannot be fingerprinted — the URL is the URL. Use `Cache-Control: no-cache` which forces revalidation with the server on every request but allows the browser to use its cached copy if the server confirms freshness (304 response). This ensures users always get the latest HTML while avoiding full re-downloads when nothing changed.
Implementation
Response header: `Cache-Control: no-cache`. The browser will send `If-Modified-Since` or `If-None-Match` headers. If content is unchanged, the server returns 304 (use cache) — fast. If changed, returns 200 with new content. IMPORTANT: `no-cache` does NOT mean "don't cache" — it means "always revalidate before serving from cache". For truly uncacheable content (banking, real-time data), use `Cache-Control: no-store`.
Accessibility
Caching has no direct accessibility impact. However, stale HTML can cause users to interact with outdated forms or broken references, which is disorienting for all users including those on assistive technology.
Cache-Control for Fingerprinted Assets seo-035
Static assets with content-hash filenames (style.ae3f66.css, app.1be87a.js) can be cached aggressively — the filename changes when content changes, so the URL is effectively immutable. Use `max-age=31536000, immutable` for maximum caching. The `immutable` directive tells the browser to skip revalidation even on user refresh.
Implementation
Response header: `Cache-Control: max-age=31536000, immutable`. Requires build-time fingerprinting (Vite, webpack, esbuild all do this by default). The filename hash ensures a new URL when content changes, so stale cache is never a problem. This is the single most impactful caching optimization — it eliminates all network requests for static assets on repeat visits. ANTI-PATTERN: Never apply `immutable` to mutable filenames (style.css without a hash). ANTI-PATTERN: Query-string versioning (style.css?v=1.2) is unreliable — CDNs and proxies may strip or ignore query params.
Accessibility
No accessibility impact. Faster asset loading benefits all users, especially those on slower connections or assistive technology that adds rendering overhead.
Cache-Control for Dynamic API Data seo-036
API responses need caching strategies that balance freshness against latency. Use `stale-while-revalidate` to serve cached data instantly while fetching fresh data in the background — the user sees content immediately and gets updated data on the next request. For real-time data (prices, scores), use `no-cache` or `no-store`.
Implementation
Non-critical data: `Cache-Control: max-age=60, stale-while-revalidate=300` — serve from cache for 60s, then serve stale for up to 5 more minutes while revalidating. Critical data: `Cache-Control: no-cache` — always revalidate. Sensitive data: `Cache-Control: private, no-store` — never cache (banking, personal data). CDN layer: use `s-maxage` to set different CDN vs browser cache times: `Cache-Control: max-age=0, s-maxage=3600` — CDN caches for 1 hour, browser always revalidates. Add `Vary: Accept-Encoding` for compressed responses.
Accessibility
No direct accessibility impact. Faster API responses reduce perceived wait times, which benefits users with cognitive disabilities who may lose context during loading.
Cache-Control for Images & Media seo-037
Images and media files are typically the heaviest assets on a page. Use aggressive caching with revalidation fallback: `max-age=2419200, must-revalidate, stale-while-revalidate=86400` for general images (28 days cached, 1 day stale grace). For fingerprinted images from a CDN/image pipeline, use the immutable strategy. For user-uploaded content, use shorter durations with revalidation.
Implementation
Fingerprinted images (CDN-optimized): `Cache-Control: max-age=31536000, immutable`. General images (not fingerprinted): `Cache-Control: max-age=2419200, must-revalidate, stale-while-revalidate=86400`. User avatars/uploads (may change): `Cache-Control: max-age=3600, must-revalidate`. Always pair with `ETag` or `Last-Modified` headers for efficient revalidation. ANTI-PATTERN: Caching user-specific images (profile photos) with `public` — use `private` to prevent CDN caching of personal content.
Accessibility
No direct accessibility impact. Cached images avoid layout shift from re-downloads, which benefits users with motion sensitivities and screen magnification users.
Cache Busting Strategy seo-038
Cache busting ensures users get new assets when content changes. Content-hash fingerprinting (style.ae3f66.css) is the only reliable method — the URL changes when content changes. Query-string versioning (style.css?v=1.2) is unreliable because CDNs and proxies may strip query parameters. Never use mutable filenames with aggressive caching — it locks users into stale assets with no way to force a refresh.
Implementation
Best: Content-hash filenames generated by build tools (Vite, webpack, esbuild). The hash is derived from file content, so any change produces a new filename. Set `Cache-Control: max-age=31536000, immutable` on these files. HTML references the new filename automatically. Nuclear option: `Clear-Site-Data: "cache"` response header on a specific endpoint to force-clear all cached assets for the origin (use sparingly — clears everything). NEVER: Rely on filename-based versioning (style-v2.css) — humans forget to bump versions.
Accessibility
No direct accessibility impact. Proper cache busting prevents users from experiencing broken layouts caused by stale CSS/JS assets.
Stale-While-Revalidate Pattern seo-039
The `stale-while-revalidate` directive lets the browser serve a stale cached response immediately while revalidating in the background. The user sees content instantly (from cache) and gets fresh content on the next visit. This is the best pattern for non-critical content where a momentarily-outdated response is acceptable for a massive speed gain.
Implementation
`Cache-Control: max-age=3600, stale-while-revalidate=86400`. Translation: serve from cache for 1 hour. After 1 hour, serve stale but revalidate in background — for up to 24 more hours. After 25 hours total, must fully revalidate before serving. Pair with `stale-if-error=86400` to serve stale content if the server returns 5xx errors: `Cache-Control: max-age=3600, stale-while-revalidate=86400, stale-if-error=86400`. This provides resilience during outages — users see cached content instead of error pages.
Accessibility
No direct accessibility impact. SWR improves perceived performance for all users. Content freshness is usually acceptable for the brief stale window.