Website Health & AI-Readiness Report
What we found, and what it means
The short version, written for decision-makers — not developers.
We audited 25 pages of books.toscrape.com and the site scored 31 overall — a failing grade driven almost entirely by fixable technical basics. Security (34), Core SEO (37) and Performance (41) are the weak spots, while accessibility (74) and site integrity are genuinely strong. In practice, this means search engines can find you but don't reliably rank you, and some visitors wait longer than they should for pages to appear.
Three problems dominate. Every page loads at least one insecure HTTP resource on an HTTPS page, which browsers may block and which erodes visitor trust. Twenty of 25 pages have no meta description, so Google writes its own snippet and your click-through rate suffers. And slow, unminified, duplicate JavaScript with no caching makes pages heavier than necessary.
The encouraging news: 2,047 checks passed, and the site scores a perfect 100 on AI-readiness and mobile. Fixing the SEO basics, the mixed content and the performance issues would likely lift the score into the B range. That translates directly into more impressions, more clicks and a faster site that converts better — without a redesign.
The five issues costing you the most
Ranked by business impact — severity × category weight × pages affected.
errorMeta Description
20 of your 25 pages have no meta description, so Google improvises a snippet from page text. You're handing control of your shop-window copy to an algorithm. Writing 120–160 character descriptions per page typically lifts click-through from search results meaningfully — free traffic you're currently leaving on the table.
errorMixed Content
Every single page loads at least one file over insecure HTTP despite the site being HTTPS. Browsers may silently block these resources, and visitors see security warnings that damage trust at the exact moment they're deciding whether to buy. Updating those URLs to HTTPS is usually a one-line-per-file fix and instantly restores the padlock's credibility.
warningCanonical URL
No page declares a canonical URL, so if the same content is reachable via slightly different URLs (query strings, pagination), Google may index duplicates and dilute your ranking signals across copies. One self-referencing canonical tag per page fixes this cheaply and concentrates your search equity where it earns.
warningCharset
Checks for proper character encoding declaration
<head> section. This tells browsers how to interpret the text on your page. UTF-8 is the standard encoding that supports all languages and special characters. Placing it first ensures browsers know the encoding before parsing any other content.warningOpen Graph Tags
Validates Open Graph meta tags for social sharing
Every category, scored
15 categories scored 0–100, weakest first, with analyst notes.
This is the site's standout strength: a perfect 100 for AI-readiness and Agent Experience. ChatGPT, Perplexity and Google's AI overviews can crawl, parse and cite your pages cleanly today. As AI assistants increasingly shape where customers go, this is worth protecting — any redesign or added JavaScript clutter should preserve it. Most competitors are far behind here; keep it that way.
Your HTTP security, examined
Beyond the crawl, a dedicated check pack probed your live server: response headers, session cookies, TLS handshakes and the certificate chain.
| Check | Result | What we saw |
|---|---|---|
| Strict-Transport-Security (HSTS) | In your fix list | max-age=0; includeSubDomains; preload — already reported by engine rule security/hsts |
| Content-Security-Policy quality | In your fix list | already reported by engine rule security/csp |
| X-Content-Type-Options | Warning | header missing — browsers may MIME-sniff responses |
| Referrer-Policy | Warning | header missing — browsers default to leaking the full URL cross-origin in legacy cases |
| Permissions-Policy | Warning | header missing — powerful browser features opt in by default |
| Clickjacking protection | In your fix list | absent — already reported by engine rule security/x-frame-options |
| Session-cookie flags | Passed | no cookies set on the probe response |
| TLS minimum version | Passed | TLSv1.3 — legacy TLS 1.0/1.1 refused |
| Certificate chain expiry | Error | 25 day(s) left — certificate chain expires within 30 days |
| Technology banners | Passed | absent — no version detail disclosed |
Included with every paid report. This security examination — TLS handshakes, certificate chain, cookie flags, header quality — runs on every report we sell. The free scorecard doesn't check any of it.
Would an AI recommend you?
Readable is half the job. We also asked an AI, the way a buyer would, whether it recommends you — 5 real shopping questions, one snapshot each.
| What buyers ask | You | Who the AI named |
|---|---|---|
| best online bookstore for classic science fiction anthologies | not named | AbeBooks · Amazon · Barnes & Noble |
| where can I buy cheap poetry collections like Shel Silverstein online | not named | Amazon · ThriftBooks · AbeBooks“Shel Silverstein is a famous American children's poet, widely available online.” |
| Mesaerion Best Science Fiction Stories 1800-1849 where to buy | not named | Amazon · AbeBooks · Barnes & Noble“Mesaerion appears to be a small/obscure publisher of this anthology; I'm not familiar with it, so a used-book search is advisable.” |
| is Books to Scrape a legit place to order books | not named | AbeBooks · Better World Books · Amazon Books“Books to Scrape is a fake demo site created for web-scraping tutorials, not a real store.” |
| who sells curated classic literature collections online with good prices | not named | ThriftBooks · Better World Books · Barnes & Noble |
Ship Organization / LocalBusiness schema with one consistent name, address and set of facts, so assistants hold a canonical record of you instead of guessing.
Publish the comparison and “best online bookstore (new books by genre) in …” pages buyers actually ask about — checkable facts and prices, not slogans.
llms.txt, FAQ schema and plain-text prices and locations give assistants something safe to quote — the AI-Readiness fixes in your plan are the prerequisites.
Builds on the 2 AI-Readiness items already in your fix plan below.
Method: single-assistant snapshot via API (glm-5.3 via API, October 21, 2026) — one answer per buyer question. Not live ChatGPT/Perplexity tracking.
Every finding, ready for your AI
Each item is self-contained — what's wrong, where on the live site, how to fix it, how to verify. Copy the checklist into Claude Code, Cursor, or Codex; no repository needed.
Full evidence for every item travels in the copied/downloaded checklist.
- What's wrong
- Validates meta description presence and length (Missing meta description) (Description too long)
- Where
- https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html — It's hard to imagine a world without A Light (1023 chars); https://books.toscrape.com/catalogue/its-only-the-himalayas_981/index.html — “Wherever you go, whatever you do, just . . . (1411 chars); https://books.toscrape.com/catalogue/libertarianism-for-beginners_982/index.html — Libertarianism isn't about winning elections; (1255 chars); +19 more in the copied checklist
- The fix:
- Meta descriptions should be 120-160 characters and provide a compelling summary of the page. While not a direct ranking factor, good descriptions improve click-through rates from search results. Write unique descriptions for each page that accurately preview the content. Include a call-to-action when appropriate. If missing, search engines will auto-generate snippets which may not represent your page optimally.
- Verify
- every affected page carries one `<meta name="description">` of ~70–160 characters
- What's wrong
- Checks for HTTP resources on HTTPS pages (1 HTTP resource(s) on HTTPS page)
- Where
- http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
- The fix:
- Mixed content occurs when an HTTPS page loads resources over HTTP, breaking the security chain. Browsers may block these resources. Update all resource URLs to use HTTPS or protocol-relative URLs (//example.com). Check images, scripts, stylesheets, fonts, and iframes. Use Content-Security-Policy: upgrade-insecure-requests to automatically upgrade HTTP to HTTPS.
- Verify
- no `http://` subresources remain on any https page — the browser console is clean
- What's wrong
- Validates canonical URL presence and format (Missing canonical URL)
- Where
- https://books.toscrape.com/; https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html; https://books.toscrape.com/catalogue/category/books/travel_2/index.html
- The fix:
- Canonical URLs tell search engines which version of a page is the "master" copy, preventing duplicate content issues. Every page should specify a canonical URL, typically pointing to itself. Add a <link rel="canonical" href="..."> tag in the head section. Use absolute URLs and ensure consistency (with or without trailing slash, www vs non-www). For paginated content, point to the main page or use rel="prev/next".
- Verify
- each page's `rel=canonical` points at its own absolute URL — `curl -s <url> | grep -i canonical`
- What's wrong
- Checks for proper character encoding declaration (No charset declaration found)
- Where
- https://books.toscrape.com/; https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html; https://books.toscrape.com/catalogue/category/books/travel_2/index.html
- The fix:
- Add <meta charset="UTF-8"> as the first element in your
<head>section. This tells browsers how to interpret the text on your page. UTF-8 is the standard encoding that supports all languages and special characters. Placing it first ensures browsers know the encoding before parsing any other content. - Verify
- the charset declaration is present and matches the served `Content-Type` header
- What's wrong
- Validates Open Graph meta tags for social sharing (Missing og:description) (Missing og:image - social shares will lack imagery)
- Where
- https://books.toscrape.com/; https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html; https://books.toscrape.com/catalogue/category/books/travel_2/index.html
- The fix:
- Open Graph tags control how your content appears when shared on Facebook, LinkedIn, and other platforms. Required tags: og:title, og:description, og:image, og:url, and og:type. Add OG tags in your page head. Use images at least 1200x630 pixels for best display. Keep og:title under 60 characters and og:description under 200. Test shares using Facebook's Sharing Debugger tool.
- Verify
- og:title / og:description / og:image resolve on every page (any sharing debugger renders the card)
- What's wrong
- Checks for CSS files that exceed recommended size limits (1 CSS file(s) exceed 150.0 KB)
- Where
- https://books.toscrape.com/static/oscar/css/styles.css
- The fix:
- Large CSS files slow down rendering and increase bandwidth. Split large stylesheets into smaller chunks, remove unused selectors, and minify CSS. Consider critical CSS inlining for above-the-fold styles and lazy-loading non-critical CSS.
- Verify
- flagged stylesheets are under the budget shown above after minification/pruning
- What's wrong
- Identifies chains of dependent resources that delay rendering (3 critical request chain(s) found)
- Where
- CSS: ../../../../static/oscar/css/datetimepicker.css; CSS: ../../../../static/oscar/css/styles.css; CSS: ../../../../static/oscar/js/bootstrap-datetimepicker/bootstrap-datetimepicker.css; +12 more in the copied checklist
- The fix:
- Critical request chains are sequences of dependent network requests that must complete before the page can render. Reduce chain depth by: 1) Inlining critical CSS instead of linking external files. 2) Adding async or defer to non-critical scripts. 3) Avoiding CSS @import — use
<link>tags instead. 4) Using <link rel='preload'> for critical resources. 5) Reducing the number of render-blocking resources in<head>. - Verify
- re-measure with PageSpeed Insights — the flagged metric is in the green
- What's wrong
- Detects duplicate JavaScript libraries loaded multiple times (1 library(s) loaded multiple times)
- Where
- bootstrap-datetimepicker (2x)
- The fix:
- Remove duplicate JavaScript library loads to reduce page weight and avoid conflicts. Check for the same library loaded from different CDNs or versions. Use a single source for each dependency. Consider using a module bundler to deduplicate shared dependencies.
- Verify
- re-measure with PageSpeed Insights — the flagged metric is in the green
- What's wrong
- Detects JavaScript libraries and checks for known vulnerabilities (2 JavaScript library/libraries detected) (1 library/libraries with known vulnerabilities)
- Where
- script URL; vulnerable; XSS vulnerability in jQuery.htmlPrefilter
- The fix:
- Keep JavaScript libraries updated to their latest versions. Outdated libraries may contain security vulnerabilities that attackers can exploit. Consider replacing large libraries like jQuery with modern vanilla JavaScript or smaller alternatives. Use npm audit or Snyk to monitor dependencies for vulnerabilities.
- Verify
- re-measure with PageSpeed Insights — the flagged metric is in the green
- What's wrong
- Detects unminified JavaScript that could be optimized (3 JavaScript file(s) appear unminified)
- Where
- 31.2KB, ~5.7KB savings; 54.0KB, ~15.1KB savings; 13.6KB, ~6.3KB savings
- The fix:
- Minify JavaScript to reduce file size and improve load times. Use build tools like Terser, esbuild, or UglifyJS. Most bundlers (Webpack, Vite, Rollup) minify automatically in production. Minification shortens variable names, removes whitespace, and dead code.
- Verify
- re-measure with PageSpeed Insights — the flagged metric is in the green
- What's wrong
- Checks Cache-Control header configuration (No caching headers found)
- Where
- https://books.toscrape.com/; https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html; https://books.toscrape.com/catalogue/category/books/travel_2/index.html
- The fix:
- Use Cache-Control headers to enable browser caching. For static assets (CSS, JS, images), set long max-age (1 year) with immutable when using hashed filenames. For HTML, use shorter max-age or no-cache with revalidation. Example: 'Cache-Control: public, max-age=31536000, immutable' for versioned assets.
- Verify
- re-measure with PageSpeed Insights — the flagged metric is in the green
- What's wrong
- Flags the hero/LCP image when it is eagerly loaded but has neither fetchpriority='high' nor a preload (Hero/LCP image loaded eagerly without fetchpriority='high' or preload)
- Where
- 27a53d0bb95bdd88288eaf66c9230d7e.jpg; 2cdad67c44b002e7ead0cc35693c0e8b.jpg; 08e94f3731d7d6b760dfbfbc02ca5c62.jpg; +20 more in the copied checklist
- The fix:
- The Largest Contentful Paint image should be discovered and fetched as early as possible. When the hero image is loaded eagerly but left at default priority, the browser races it against other resources and LCP suffers. Add fetchpriority='high' to the LCP
<img>so the browser prioritises it, or preload it with <link rel='preload' as='image' href='...' fetchpriority='high'>. Either signal is enough; you do not need both. Only apply this to the single above-fold LCP image, never to below-fold images. - Verify
- re-measure with PageSpeed Insights — the flagged metric is in the green
- What's wrong
- Checks for Largest Contentful Paint optimization opportunities (1 likely-LCP image loaded without preload) (2 to 3 likely-LCP images loaded without preload)
- Where
- https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html — 1 likely-LCP image loaded without preload; https://books.toscrape.com/ — 3 likely-LCP images loaded without preload; https://books.toscrape.com/catalogue/category/books/travel_2/index.html — 3 likely-LCP images loaded without preload; +22 more in the copied checklist
- The fix:
- LCP measures when the largest content element becomes visible. Optimize by: 1) Preload your LCP image with <link rel='preload' as='image'>. 2) Don't use loading='lazy' on above-fold images as it delays loading. 3) Minimize render-blocking CSS/JS in
<head>. 4) Use modern image formats (WebP/AVIF) for faster loading. 5) Consider using fetchpriority='high' on the LCP image. - Verify
- LCP is under 2.5s — re-measure with PageSpeed Insights on the affected pages
- What's wrong
- Checks if XML sitemap exists and is referenced in robots.txt (No XML sitemap found)
- Where
- —
- The fix:
- XML sitemaps help search engines discover and index your pages. Create a sitemap.xml at your domain root listing all important pages. Reference it in robots.txt with 'Sitemap: https://yoursite.com/sitemap.xml'. Submit it to Google Search Console and Bing Webmaster Tools. Keep it under 50MB and 50,000 URLs per file; use a sitemap index for larger sites.
- Verify
- `/sitemap.xml` returns 200, is valid XML, lists only live URLs, and is referenced from robots.txt
- What's wrong
- Checks if robots.txt exists and is properly configured (No robots.txt found)
- Where
- —
- The fix:
- robots.txt tells search engines which pages to crawl. Place it at the root of your domain (example.com/robots.txt). Include your sitemap URL. Avoid blocking important resources (CSS, JS, images) that search engines need to render pages. Never use 'Disallow: /' unless you want to block all crawling. Use Google Search Console to test your robots.txt.
- Verify
- `/robots.txt` returns 200 and does not block key paths — `curl -sI <url>/robots.txt`
- What's wrong
- Checks for Cumulative Layout Shift prevention (6 to 20 image(s) without width/height (CLS risk)) (1 to 5 image(s) without width/height (CLS risk))
- Where
- ../../../../media/cache/06/81/0681530a7bc301caf5c3257e1b0f0750.jpg; ../../../../media/cache/27/a5/27a53d0bb95bdd88288eaf66c9230d7e.jpg; ../../../../media/cache/4e/15/4e15150388702ebca2c5a523ac270539.jpg; +107 more in the copied checklist
- The fix:
- CLS measures visual stability - how much content shifts during load. Prevent layout shifts by: 1) Always set width and height attributes on images and iframes. 2) Reserve space for ads and embeds with CSS min-height. 3) Use CSS aspect-ratio for responsive media. 4) Avoid inserting content above existing content. 5) Use transform animations instead of properties that trigger layout.
- Verify
- CLS is under 0.1 — re-measure with PageSpeed Insights on the affected pages
- What's wrong
- Checks that cross-origin scripts and stylesheets use Subresource Integrity (SRI) (1 cross-origin resource without Subresource Integrity)
- Where
- http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js — script
- The fix:
- Cross-origin scripts and stylesheets can be tampered with in transit or at the source (a compromised CDN or third-party host), and the browser has no way to detect it without help. Add an integrity attribute with a sha256/sha384/sha512 hash of the expected file, plus crossorigin="anonymous": <script src="..." integrity="sha384-..." crossorigin="anonymous">
</script>. Most CDNs (jsDelivr, cdnjs, unpkg) publish the hash alongside the URL. This only works for pinned/versioned assets — scripts that update themselves server-side (analytics, payment SDKs, CAPTCHAs) intentionally don't support it. - Verify
- external `<script>`/`<link>` tags carry `integrity` + `crossorigin` attributes
- What's wrong
- Validates page title presence and length (Title too long)
- Where
- https://books.toscrape.com/catalogue/mesaerion-the-best-science-fiction-stories-1800-1849_983/index.html — Mesaerion: The Best Science Fiction Stories 1 (87 chars); https://books.toscrape.com/catalogue/our-band-could-be-your-life-scenes-from-the-american-indie-underground-1981-1991_985/index.html — Our Band Could Be Your Life: Scenes from the (116 chars); https://books.toscrape.com/catalogue/scott-pilgrims-precious-little-life-scott-pilgrim-1_987/index.html — Scott Pilgrim's Precious Little Life (Scott P (89 chars); +4 more in the copied checklist
- The fix:
- Every page needs a unique, descriptive title tag between 30-75 characters. Titles appear in browser tabs, search results, and social shares. Write titles that accurately describe the page content while including your primary keyword near the beginning. If your title is too short, add more descriptive context. If too long, prioritize the most important information first and trim secondary details. Avoid keyword stuffing or duplicate titles across pages.
- Verify
- every affected page has a single `<title>`, 30–60 characters, unique across the site
- What's wrong
- Checks that page titles are unique across the site (1 duplicate title(s) affecting 3 pages)
- Where
- "all products | books to scrape - sandbox..." (3 pages)
- The fix:
- Each page should have a unique title that accurately describes its content. Duplicate titles confuse search engines and users about which page to display. Use a pattern like 'Page Topic | Brand Name' to ensure uniqueness. CMS often generate duplicate titles - audit and customize them.
- Verify
- no two audited pages share a `<title>` — `curl -s <url> | grep -i '<title>'`
- What's wrong
- The HTTPS certificate chain expires in 25 day(s) — when it lapses, browsers show a full-page warning and traffic stops.
- Where
- 25d left
- The fix:
- Renew now and set up automated renewal (ACME) with monitoring — a chain expiring this soon means renewal is not automated.
- Verify
- the renewed certificate chain has >30 days of validity — `openssl s_client -connect <host>:443 -servername <host> </dev/null 2>/dev/null | openssl x509 -noout -enddate`
- What's wrong
- Validates Twitter Card meta tags (No Twitter card or Open Graph tags for Twitter sharing)
- Where
- https://books.toscrape.com/; https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html; https://books.toscrape.com/catalogue/category/books/travel_2/index.html
- The fix:
- Twitter Cards enhance how links appear in tweets. The twitter:card meta tag specifies the card type (summary, summary_large_image, player, or app). Add twitter:card, twitter:title, twitter:description, and twitter:image tags. For large images, use summary_large_image with images at least 800x418 pixels. Validate using Twitter's Card Validator tool.
- Verify
- re-fetch each affected page and confirm the flagged tag is present and well-formed
- What's wrong
- Checks that the page has exactly one main landmark (Page has no main landmark)
- Where
- https://books.toscrape.com/; https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html; https://books.toscrape.com/catalogue/category/books/travel_2/index.html
- The fix:
- Each page should have exactly one
<main>element or element with role='main'. This helps screen reader users quickly navigate to the primary content. Multiple main landmarks confuse navigation. Use<aside>,<nav>, or other landmarks for secondary content. - Verify
- re-scan with axe-core (or a keyboard pass) on the affected pages — zero violations of this rule
- What's wrong
- Checks for bypass mechanisms for keyboard navigation (No bypass mechanism for repetitive content)
- Where
- https://books.toscrape.com/; https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html; https://books.toscrape.com/catalogue/category/books/travel_2/index.html
- The fix:
- Skip links allow keyboard users to bypass repetitive navigation and jump directly to main content. Add a hidden link at the very beginning of your page: <a href='#main-content' class='skip-link'>Skip to main content
</a>. Style it to become visible on focus. Ensure the target (#main-content) has tabindex='-1' if it's not naturally focusable. Alternative: use landmark roles like<main>which screen readers can navigate to directly. - Verify
- re-scan with axe-core (or a keyboard pass) on the affected pages — zero violations of this rule
- What's wrong
- Detects excessive keyword repetition in content (1 to 4 word(s) may be overused)
- Where
- "add" (9.8%); "basket" (9.3%); "dans" (3.5%); +8 more in the copied checklist
- The fix:
- Keyword stuffing is repeating words unnaturally to manipulate rankings. Search engines penalize this practice. Write naturally for users first. Use keywords where they fit naturally. Aim for 1-2% keyword density at most. Use synonyms and related terms instead of repeating the exact same phrase. Focus on providing value, not gaming algorithms.
- Verify
- spot-check the affected pages — the flagged pattern is gone
- What's wrong
- Flags sites where most pages lack caching freshness, validators, or compression (25/25 pages set no caching policy (no freshness lifetime and no validator))
- Where
- https://books.toscrape.com/; https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html; https://books.toscrape.com/catalogue/category/books/travel_2/index.html
- The fix:
- Set Cache-Control with an appropriate max-age on every response (short for HTML, long + immutable for hashed static assets), expose an ETag or Last-Modified for cheap revalidation, and enable gzip/Brotli for text responses. Consistent caching across the whole site cuts repeat-visit load times and origin/CDN cost.
- Verify
- static assets return long-lived `Cache-Control` max-age — `curl -sI <asset>`
- What's wrong
- Checks content length for thin content issues (Thin content: 219 to 288 words (min 300))
- Where
- https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html — Thin content: 234 words (min 300); https://books.toscrape.com/catalogue/category/books/travel_2/index.html — Thin content: 219 words (min 300); https://books.toscrape.com/catalogue/rip-it-up-and-start-again_986/index.html — Thin content: 283 words (min 300); +6 more in the copied checklist
- The fix:
- Pages with thin content (under 300 words) often struggle to rank well and are actively deindexed by Google since the June 2025 core update. Add more valuable, relevant content to thin pages—aim for at least 500 words for standard pages and 1000+ for in-depth articles. If a page can't be fleshed out, voluntarily noindex it or consolidate it into a more comprehensive resource. Trimming thin pages from your index is better than leaving low-value content for Google to penalize.
- Verify
- listed pages carry ≥300 words of real body content
- What's wrong
- Checks for Interaction to Next Paint optimization (5 blocking scripts (consider async/defer))
- Where
- https://books.toscrape.com/ — 5 blocking scripts (consider async/defer); https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html — 5 blocking scripts (consider async/defer); https://books.toscrape.com/catalogue/category/books/travel_2/index.html — 5 blocking scripts (consider async/defer); +22 more in the copied checklist
- The fix:
- INP measures responsiveness to user interactions. Improve by: 1) Minimize third-party scripts that block the main thread. 2) Use async/defer for non-critical scripts. 3) Break up long JavaScript tasks into smaller chunks. 4) Use web workers for heavy computations. 5) Implement code splitting to reduce initial bundle size. Consider using requestIdleCallback for non-urgent work.
- Verify
- Interaction to Next Paint is under 200ms on the affected pages
- What's wrong
- Checks for width/height attributes (prevents CLS) (1 to 20 image(s) missing width/height (causes CLS))
- Where
- https://books.toscrape.com/media/cache/06/81/0681530a7bc301caf5c3257e1b0f0750.jpg; https://books.toscrape.com/media/cache/08/e9/08e94f3731d7d6b760dfbfbc02ca5c62.jpg; https://books.toscrape.com/media/cache/09/a3/09a3aef48557576e1a85ba7efea8ecb7.jpg; +67 more in the copied checklist
- The fix:
- Specifying width and height attributes prevents Cumulative Layout Shift (CLS) by reserving space before images load. Add width and height attributes to img tags matching the image's intrinsic dimensions. Use CSS for responsive sizing if needed. For responsive images, the aspect ratio from width/height prevents layout shifts even when CSS overrides the actual size.
- Verify
- every `<img>` declares `width` and `height` (or aspect-ratio) to stop layout shift
- What's wrong
- Checks if offscreen images use lazy loading (1 to 17 below-fold image(s) without lazy loading)
- Where
- 0681530a7bc301caf5c3257e1b0f0750.jpg; 0f7ee69495c0df1d35723f012624a9f8.jpg; 1048f63d3b5061cd2f424d20b3f9b666.jpg; +32 more in the copied checklist
- The fix:
- Add loading='lazy' to images below the fold to defer loading until needed. This reduces initial page load time and saves bandwidth. Exception: Don't lazy-load LCP image or above-the-fold content. Use loading='eager' for critical images.
- Verify
- view-source on the affected pages — the flagged attribute is present on every image
- What's wrong
- No X-Content-Type-Options header — browsers may second-guess the served Content-Type and execute an upload as script.
- Where
- missing
- The fix:
- Send X-Content-Type-Options: nosniff on every response.
- Verify
- `curl -sI <url> | grep -i x-content-type-options` shows exactly `nosniff`
- What's wrong
- No Referrer-Policy header — the browser default can leak full URLs (paths, query strings, tokens) to third-party sites.
- Where
- missing
- The fix:
- Send Referrer-Policy: strict-origin-when-cross-origin (or stricter) on every response.
- Verify
- `curl -sI <url> | grep -i referrer-policy` shows `strict-origin-when-cross-origin` or stricter
- What's wrong
- No Permissions-Policy header — camera, microphone, geolocation and similar features are available to any embedded content unless the site opts out.
- Where
- missing
- The fix:
- Send Permissions-Policy with a deny-by-default list, e.g. camera=(), microphone=(), geolocation=(), then re-enable per page where needed.
- Verify
- responses carry a Permissions-Policy header — `curl -sI <url> | grep -i permissions-policy`
- What's wrong
- Validates heading structure and hierarchy (Skipped heading levels detected)
- Where
- H1 -> H3
- The fix:
- Proper heading structure (H1 → H2 → H3) helps users and search engines understand your content organization. Skipping levels (H1 → H3) creates confusion. Use headings in sequential order without skipping levels. Each section should use the next heading level down. Think of headings as an outline—they should make sense when read alone. Avoid empty headings or using headings purely for styling.
- Verify
- spot-check the affected pages — the flagged pattern is gone
- What's wrong
- Checks for Content-Security-Policy header and validates directives (No Content-Security-Policy header)
- Where
- —
- The fix:
- CSP prevents XSS attacks by restricting which resources can load. Start with a report-only policy to identify issues. Key directives: default-src 'self', script-src (avoid 'unsafe-inline'), img-src, style-src, frame-ancestors. Use nonces or hashes instead of 'unsafe-inline' for scripts. Test thoroughly as strict CSP can break functionality.
- Verify
- responses carry a Content-Security-Policy header — `curl -sI <url> | grep -i content-security-policy`
- What's wrong
- Checks for HTTP Strict Transport Security header (HSTS disabled — max-age=0 tells browsers to stop enforcing HTTPS)
- Where
- —
- The fix:
- HSTS forces browsers to only connect via HTTPS, preventing downgrade attacks. Add the header: Strict-Transport-Security: max-age=31536000; includeSubDomains. Start with a short max-age (1 day) to test, then increase to 1 year. The includeSubDomains directive protects all subdomains. Consider preloading via hstspreload.org for maximum protection.
- Verify
- `curl -sI <url> | grep -i strict-transport-security` shows `max-age` ≥ 15552000
- What's wrong
- Checks for clickjacking protection header (No clickjacking protection)
- Where
- —
- The fix:
- X-Frame-Options prevents your site from being embedded in iframes, protecting against clickjacking attacks. Set: X-Frame-Options: DENY (no framing) or SAMEORIGIN (same origin only). For modern browsers, CSP frame-ancestors is preferred: Content-Security-Policy: frame-ancestors 'self'. Use both for maximum compatibility.
- Verify
- responses carry `X-Frame-Options: DENY|SAMEORIGIN` (or a CSP `frame-ancestors` directive)
- What's wrong
- Checks for duplicate title tags across the site (1 duplicate title(s) found across 3 pages)
- Where
- "all products | books to scrape - sandbox..." (3 pages)
- The fix:
- Each page should have a unique title tag that accurately describes its content. Duplicate titles confuse search engines about which page to rank and make your pages less distinguishable in search results. Use unique, descriptive titles that include relevant keywords. For similar pages (e.g., pagination), add differentiating elements like page numbers or category names.
- Verify
- no two audited pages share a title
- What's wrong
- Checks that heading levels don't skip (1 heading level skip(s) detected)
- Where
- H3 after H1
- The fix:
- Headings should follow a logical hierarchy without skipping levels. Screen reader users navigate by headings, so skipping from H1 to H3 is confusing. Correct order: H1 -> H2 -> H3 (not H1 -> H3). You can have multiple headings at the same level, and you can go back up (H3 -> H2 is fine). Think of headings as an outline - they should make sense when read alone.
- Verify
- re-scan with axe-core (or a keyboard pass) on the affected pages — zero violations of this rule
- What's wrong
- Checks for an about/company page with content (No About page found)
- Where
- —
- The fix:
- An About page establishes credibility and trust. Include company history, mission, team overview, and credentials. Link from main navigation or footer. For E-E-A-T, explain your expertise and why visitors should trust you. Include contact information and physical location if applicable.
- Verify
- the about page returns 200 and names who runs the site
- What's wrong
- Checks for contact page with multiple contact methods (No Contact page found)
- Where
- —
- The fix:
- A contact page with multiple contact methods builds trust. Include: email address or contact form, phone number (if applicable), physical address, and social media links. Make contact information easy to find from any page. For local businesses, include business hours. Response time expectations are also helpful.
- Verify
- the contact page returns 200 with a usable contact route
- What's wrong
- Checks for privacy policy page linked from footer (No Privacy Policy page found)
- Where
- —
- The fix:
- A privacy policy is required by law in many jurisdictions (GDPR, CCPA) and signals trustworthiness. Link it from your footer on every page. Cover: what data you collect, how you use it, third-party sharing, user rights, and contact for privacy concerns. Keep it updated when practices change.
- Verify
- the flagged page returns 200 with the expected identity/contact content
- What's wrong
- Checks for descriptive link text (1 to 2 link(s) with generic text)
- Where
- next; previous
- The fix:
- Link text should describe the destination, not generic phrases like 'click here'. Screen reader users often navigate by links, hearing them out of context. Good: 'View our pricing plans'. Bad: 'Click here'. For icon-only links, add aria-label: <a href='/search' aria-label='Search'>
<svg>...</svg></a>. Empty links are especially problematic - add text or aria-label. - Verify
- re-scan with axe-core (or a keyboard pass) on the affected pages — zero violations of this rule
- What's wrong
- Checks that URLs use hyphens, not underscores (URL uses underscores (1) instead of hyphens)
- Where
- https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html — URL uses underscores (1) instead of hyphens; https://books.toscrape.com/catalogue/category/books/travel_2/index.html — URL uses underscores (1) instead of hyphens; https://books.toscrape.com/catalogue/category/books_1/index.html — URL uses underscores (1) instead of hyphens; +19 more in the copied checklist
- The fix:
- Use hyphens (-) to separate words in URLs, not underscores (_). Google treats hyphens as word separators but treats underscores as word joiners. 'blue-shoes' = 'blue' + 'shoes', but 'blue_shoes' = 'blueshoes'. This affects keyword matching and SEO. Replace underscores with hyphens and set up redirects from old URLs.
- Verify
- spot-check the pages listed above — the flagged condition is gone
- What's wrong
- Checks for proper landmark regions (main, nav, footer) (No <main> landmark found)
- Where
- https://books.toscrape.com/; https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html; https://books.toscrape.com/catalogue/category/books/travel_2/index.html
- The fix:
- Landmark regions help screen reader users navigate page structure. Use semantic HTML5 elements:
<main>for primary content,<nav>for navigation,<header>for page header,<footer>for footer,<aside>for sidebars, and<section>/<article>for content sections. Alternatively, use ARIA roles: role='main', role='navigation', etc. Each page should have exactly one<main>element. - Verify
- pages have main/nav/footer landmarks and one `<h1>`
- What's wrong
- Checks for privacy policy link presence (No privacy policy link found across site)
- Where
- —
- The fix:
- A privacy policy is legally required in many jurisdictions (GDPR, CCPA). Link to your privacy policy from every page, typically in the footer. The policy should explain what data you collect, how it's used, and user rights. Consider using schema.org markup to identify the policy page.
- Verify
- the privacy policy returns 200 and is linked site-wide
- What's wrong
- Detects /llms.txt (and /llms-full.txt) at the domain root and checks its basic Markdown format — an emerging standard giving AI agents a curated, machine-readable map of your site (No /llms.txt found — consider adding one so AI agents can discover your key content)
- Where
- —
- The fix:
- llms.txt (llmstxt.org) is a Markdown file at your domain root that points AI agents and answer engines at your most useful, clean content. Add a /llms.txt with an H1 title, a short summary, and sections of Markdown links to key pages; optionally add /llms-full.txt with that content inlined. This is a recommendation only — it never affects your score.
- Verify
- `/llms.txt` returns 200 with valid Markdown describing the site
- What's wrong
- Checks whether the site serves text/markdown via content negotiation (Accept: text/markdown) or exposes a .md variant of the homepage — agents increasingly prefer clean Markdown over rendered HTML (No Markdown response — consider honoring Accept: text/markdown or publishing a .md variant so agents get clean content)
- Where
- —
- The fix:
- Agents and answer engines parse Markdown more reliably than rendered HTML. Serve a Markdown representation of your key pages: honor `Accept: text/markdown` via content negotiation, and/or publish a `.md` variant (e.g. /index.md). This is a recommendation only — it never affects your score.
- Verify
- the site negotiates `Accept: text/markdown` or serves clean readable HTML for agents
- What's wrong
- Checks for image optimization indicators (Images may not be optimized - consider using an image CDN)
- Where
- https://books.toscrape.com/; https://books.toscrape.com/catalogue/category/books/travel_2/index.html; https://books.toscrape.com/catalogue/category/books_1/index.html
- The fix:
- Optimize images to reduce file sizes without visible quality loss. Use tools like Squoosh, ImageOptim, or TinyPNG. Consider using an image CDN (Cloudinary, Imgix, Cloudflare Images) for automatic optimization and responsive delivery. Modern formats (WebP, AVIF) offer 25-50% better compression.
- Verify
- view-source on the affected pages — the flagged attribute is present on every image
- What's wrong
- Checks for a sub-processor / data-processing (DPA) disclosure page or link (No sub-processor / data-processing (DPA) disclosure found)
- Where
- —
- The fix:
- Under GDPR Art. 28, processors must disclose the sub-processors they engage and offer a Data Processing Agreement (DPA). Publish a /subprocessors page listing each third party that handles customer personal data (purpose, location), keep it current, and link a DPA from your legal/trust pages. B2B SaaS and fintech buyers expect this during security review.
- Verify
- the flagged page returns 200 and is linked from the footer
- What's wrong
- Checks URL length for optimal SEO (URL is 102 to 145 characters (over 100))
- Where
- https://books.toscrape.com/catalogue/mesaerion-the-best-science-fiction-stories-1800-1849_983/index.html — URL is 104 characters (over 100); https://books.toscrape.com/catalogue/our-band-could-be-your-life-scenes-from-the-american-indie-underground-1981-1991_985/index.html — URL is 132 characters (over 100); https://books.toscrape.com/catalogue/scott-pilgrims-precious-little-life-scott-pilgrim-1_987/index.html — URL is 103 characters (over 100); +3 more in the copied checklist
- The fix:
- Shorter URLs are easier to read, share, and may rank better. Keep URLs under 75 characters when possible. URLs over 100 characters can be truncated in search results and social shares. Remove unnecessary parameters, stop words, and path segments. Use descriptive but concise slugs. Long URLs often indicate poor site architecture.
- Verify
- spot-check the pages listed above — the flagged condition is gone