{
  "schema": 1,
  "id": "demo-hollow-oak",
  "url": "https://hollowoak.example/",
  "host": "hollowoak.example",
  "productUrl": "https://hollowoak.example/product/ethiopia-guji-natural/",
  "scannedAt": "2026-10-06T09:14:00.000Z",
  "durationMs": 1400,
  "demo": true,
  "siteName": "Hollow Oak Coffee Roasters",
  "platform": {
    "platform": "woocommerce",
    "confidence": "high",
    "signals": [
      "WooCommerce generator meta tag",
      "/wp-content/plugins/woocommerce/ assets",
      "woocommerce body or element classes",
      "WordPress REST API header"
    ]
  },
  "score": 44,
  "rawScore": 58,
  "cap": {
    "max": 44,
    "reason": "robots.txt blocks the main AI search agents",
    "checkId": "access.robots-search"
  },
  "grade": "E",
  "pillars": [
    {
      "pillar": "access",
      "score": 63,
      "counts": {
        "pass": 6,
        "warn": 0,
        "fail": 2,
        "info": 1
      }
    },
    {
      "pillar": "understanding",
      "score": 77,
      "counts": {
        "pass": 3,
        "warn": 3,
        "fail": 1,
        "info": 0
      }
    },
    {
      "pillar": "trust",
      "score": 30,
      "counts": {
        "pass": 0,
        "warn": 2,
        "fail": 2,
        "info": 0
      }
    },
    {
      "pillar": "transaction",
      "score": 52,
      "counts": {
        "pass": 2,
        "warn": 1,
        "fail": 1,
        "info": 1
      }
    }
  ],
  "checks": [
    {
      "id": "access.reachable",
      "pillar": "access",
      "title": "Homepage answers an agent",
      "weight": 3,
      "why": "Every agent starts with an HTTP request. Anything other than a fast 200 with HTML ends the visit before it begins.",
      "status": "pass",
      "score": 1,
      "summary": "HTTP 200.",
      "evidence": [
        {
          "label": "Status",
          "value": "200"
        },
        {
          "label": "Final URL",
          "value": "https://hollowoak.example/"
        },
        {
          "label": "Redirects",
          "value": "0"
        },
        {
          "label": "Content-Type",
          "value": "text/html; charset=UTF-8"
        }
      ]
    },
    {
      "id": "access.botwall",
      "pillar": "access",
      "title": "No bot wall in front of the store",
      "weight": 3,
      "why": "Bot-protection that challenges every non-browser client blocks AI agents even when robots.txt welcomes them. Agents cannot solve JavaScript challenges or CAPTCHAs.",
      "status": "pass",
      "score": 1,
      "summary": "Bots and browsers receive the same page.",
      "evidence": [
        {
          "label": "As LegibleBot",
          "value": "HTTP 200",
          "status": "pass"
        },
        {
          "label": "As a browser",
          "value": "HTTP 200",
          "status": "pass"
        },
        {
          "label": "Size difference",
          "value": "0 KB"
        }
      ]
    },
    {
      "id": "access.robots-search",
      "pillar": "access",
      "title": "AI search and shopping agents are allowed",
      "weight": 5,
      "why": "Search agents (OAI-SearchBot, Claude-SearchBot, PerplexityBot, Googlebot, Bingbot) build the indexes assistants search before recommending a product. User-triggered agents (ChatGPT-User, Claude-User, Perplexity-User) fetch your page while a shopper waits. Blocking either removes you from the answer.",
      "status": "fail",
      "score": 0,
      "summary": "robots.txt blocks OAI-SearchBot, Claude-SearchBot and PerplexityBot. These agents decide whether your products appear in AI search answers.",
      "evidence": [
        {
          "label": "OAI-SearchBot (OpenAI)",
          "value": "Blocked on / by \"Disallow: /\" (line 15)",
          "status": "fail"
        },
        {
          "label": "ChatGPT-User (OpenAI)",
          "value": "Blocked on / by \"Disallow: /\" (line 15)",
          "status": "fail"
        },
        {
          "label": "Claude-SearchBot (Anthropic)",
          "value": "Blocked on / by \"Disallow: /\" (line 15)",
          "status": "fail"
        },
        {
          "label": "Claude-User (Anthropic)",
          "value": "Blocked on / by \"Disallow: /\" (line 15)",
          "status": "fail"
        },
        {
          "label": "PerplexityBot (Perplexity)",
          "value": "Blocked on / by \"Disallow: /\" (line 15)",
          "status": "fail"
        },
        {
          "label": "Perplexity-User (Perplexity)",
          "value": "Allowed",
          "status": "pass"
        },
        {
          "label": "Googlebot (Google)",
          "value": "Allowed",
          "status": "pass"
        },
        {
          "label": "Bingbot (Microsoft)",
          "value": "Allowed",
          "status": "pass"
        },
        {
          "label": "Amzn-SearchBot (Amazon)",
          "value": "Allowed",
          "status": "pass"
        }
      ],
      "fix": {
        "summary": "Allow search and user-triggered agents explicitly. Keep blocking training crawlers if you want to.",
        "steps": [
          "If an SEO plugin (Yoast, Rank Math, AIOSEO) manages robots.txt, edit it there: Yoast → Tools → File editor; Rank Math → General Settings → Edit robots.txt.",
          "Check security or \"block AI\" plugins: several add blanket AI-bot blocks that include search agents.",
          "If Cloudflare is in front, check Security → Bots → \"Block AI bots\" and AI Crawl Control: these override robots.txt."
        ],
        "snippet": {
          "language": "txt",
          "filename": "robots.txt (AI agents section)",
          "code": "# --- AI agents (generated by Legible) ---\n# Before pasting: delete any existing groups for the agents named below.\n# Groups for the same agent are merged, so old rules would still apply.\n\n# Search and user-triggered agents: allowed, so products can appear\n# in ChatGPT, Claude, Perplexity, Google AI Mode and Copilot answers.\n# A named group replaces the * group, so your * rules are repeated here.\nUser-agent: OAI-SearchBot\nUser-agent: ChatGPT-User\nUser-agent: Claude-SearchBot\nUser-agent: Claude-User\nUser-agent: PerplexityBot\nUser-agent: Perplexity-User\nUser-agent: Googlebot\nUser-agent: Bingbot\nUser-agent: Amzn-SearchBot\nAllow: /\nDisallow: /wp-admin/\nAllow: /wp-admin/admin-ajax.php\nDisallow: /cart/\nDisallow: /checkout/\nDisallow: /my-account/\nDisallow: /*?add-to-cart=*\n\n# Training crawlers: your current choice is kept. Blocking them does\n# not remove you from AI search.\nUser-agent: GPTBot\nUser-agent: ClaudeBot\nUser-agent: Google-Extended\nUser-agent: Amazonbot\nUser-agent: meta-externalagent\nUser-agent: CCBot\nUser-agent: Bytespider\nDisallow: /\n\nUser-agent: Applebot-Extended\nAllow: /\nDisallow: /wp-admin/\nAllow: /wp-admin/admin-ajax.php\nDisallow: /cart/\nDisallow: /checkout/\nDisallow: /my-account/\nDisallow: /*?add-to-cart=*\n\nSitemap: https://hollowoak.example/sitemap_index.xml"
        }
      }
    },
    {
      "id": "access.robots-training",
      "pillar": "access",
      "title": "Training crawler policy",
      "weight": 0,
      "why": "Training crawlers (GPTBot, ClaudeBot, Google-Extended, CCBot and others) collect content for future models. Blocking them is a legitimate business choice and does not affect AI search visibility. Legible reports your stance but does not score it.",
      "status": "info",
      "score": null,
      "summary": "7 training crawlers blocked, 1 allowed.",
      "evidence": [
        {
          "label": "GPTBot (OpenAI)",
          "value": "Blocked"
        },
        {
          "label": "ClaudeBot (Anthropic)",
          "value": "Blocked"
        },
        {
          "label": "Google-Extended (Google)",
          "value": "Blocked"
        },
        {
          "label": "Applebot-Extended (Apple)",
          "value": "Allowed"
        },
        {
          "label": "Amazonbot (Amazon)",
          "value": "Blocked"
        },
        {
          "label": "meta-externalagent (Meta)",
          "value": "Blocked"
        },
        {
          "label": "CCBot (Common Crawl)",
          "value": "Blocked"
        },
        {
          "label": "Bytespider (ByteDance)",
          "value": "Blocked"
        }
      ]
    },
    {
      "id": "access.robots-file",
      "pillar": "access",
      "title": "robots.txt is valid",
      "weight": 1,
      "why": "RFC 9309 says a robots.txt that errors with 5xx means \"crawl nothing\", and an HTML page served as robots.txt is noise. A clean file also points agents at your sitemap.",
      "status": "pass",
      "score": 1,
      "summary": "robots.txt parses cleanly: 2 groups, 1 sitemap.",
      "evidence": [
        {
          "label": "Groups",
          "value": "2"
        },
        {
          "label": "Sitemap lines",
          "value": "1"
        },
        {
          "label": "Unrecognised lines",
          "value": "none"
        }
      ]
    },
    {
      "id": "access.sitemap",
      "pillar": "access",
      "title": "XML sitemap lists your products",
      "weight": 2,
      "why": "Crawlers that build AI search indexes discover product URLs from sitemaps far more reliably than from links, especially on large catalogues.",
      "status": "pass",
      "score": 1,
      "summary": "Valid sitemap with 6 product URLs.",
      "evidence": [
        {
          "label": "Location",
          "value": "https://hollowoak.example/sitemap_index.xml"
        },
        {
          "label": "Found via",
          "value": "robots.txt"
        },
        {
          "label": "Type",
          "value": "Sitemap index (4 child sitemaps)"
        },
        {
          "label": "Product sitemap",
          "value": "https://hollowoak.example/product-sitemap.xml (6 URLs)"
        }
      ]
    },
    {
      "id": "access.ttfb",
      "pillar": "access",
      "title": "Fast first byte",
      "weight": 2,
      "why": "User-triggered agents fetch pages while someone waits for an answer, with short timeouts. A slow server is a skipped store.",
      "status": "fail",
      "score": 0,
      "summary": "Slowest time to first byte: 1720 ms. Agents with tight timeouts will give up.",
      "evidence": [
        {
          "label": "/",
          "value": "1380 ms",
          "status": "warn"
        },
        {
          "label": "/product/ethiopia-guji-natural/",
          "value": "1720 ms",
          "status": "fail"
        }
      ],
      "fix": {
        "summary": "Cache full HTML pages so they are served without hitting the application.",
        "steps": [
          "Enable full-page caching (host cache, LiteSpeed Cache or WP Rocket) so the HTML is served without PHP on every request.",
          "Exclude only cart, checkout and my-account from the cache."
        ]
      }
    },
    {
      "id": "access.weight",
      "pillar": "access",
      "title": "Lean HTML",
      "weight": 1,
      "why": "Agents download and tokenise your HTML. Megabytes of inline scripts and styles bury product facts and can hit size caps before the content.",
      "status": "pass",
      "score": 1,
      "summary": "7 KB of HTML for /product/ethiopia-guji-natural/.",
      "evidence": [
        {
          "label": "HTML size",
          "value": "7 KB"
        },
        {
          "label": "Inline script",
          "value": "0 KB in 6 tags"
        },
        {
          "label": "Visible words",
          "value": "157"
        }
      ]
    },
    {
      "id": "access.indexable",
      "pillar": "access",
      "title": "Pages are not marked noindex",
      "weight": 2,
      "why": "A noindex meta tag or X-Robots-Tag header tells search agents to drop the page from their index, even when robots.txt allows crawling.",
      "status": "pass",
      "score": 1,
      "summary": "No noindex directives on the pages scanned.",
      "evidence": [
        {
          "label": "Homepage",
          "value": "no directive",
          "status": "pass"
        },
        {
          "label": "Product page",
          "value": "no directive",
          "status": "pass"
        }
      ]
    },
    {
      "id": "understanding.raw-html",
      "pillar": "understanding",
      "title": "Product facts are in the raw HTML",
      "weight": 5,
      "why": "Most AI fetchers do not run JavaScript. If the name, price and description only appear after scripts run, the agent sees an empty page and moves on.",
      "status": "pass",
      "score": 1,
      "summary": "Name, price and 157 words of content are in the server HTML.",
      "evidence": [
        {
          "label": "Visible words (no JS)",
          "value": "157",
          "status": "pass"
        },
        {
          "label": "Product name in text",
          "value": "Yes",
          "status": "pass"
        },
        {
          "label": "Price in text",
          "value": "16.50, 16.50, 14.90",
          "status": "pass"
        }
      ]
    },
    {
      "id": "understanding.product-schema",
      "pillar": "understanding",
      "title": "Complete Product structured data",
      "weight": 5,
      "why": "Schema.org Product and Offer JSON-LD is the most reliable way for agents and shopping indexes to read price, currency, stock, identifiers, shipping and returns without guessing from layout.",
      "status": "warn",
      "score": 0.6538461538461539,
      "summary": "Product schema is 65% complete. Missing: gtin / mpn, brand, shippingDetails, hasMerchantReturnPolicy and aggregateRating.",
      "evidence": [
        {
          "label": "name",
          "value": "Ethiopia Guji Natural",
          "status": "pass"
        },
        {
          "label": "image",
          "value": "https://hollowoak.example/wp-content/uploads/2026/09/guji.jpg",
          "status": "pass"
        },
        {
          "label": "description",
          "value": "Natural process coffee from the Guji zone. Notes of blueberry, dark chocolate an",
          "status": "pass"
        },
        {
          "label": "offers.price",
          "value": "16.5",
          "status": "pass"
        },
        {
          "label": "offers.priceCurrency",
          "value": "EUR",
          "status": "pass"
        },
        {
          "label": "offers.availability",
          "value": "http://schema.org/InStock",
          "status": "pass"
        },
        {
          "label": "sku",
          "value": "HO-GUJI-250",
          "status": "pass"
        },
        {
          "label": "gtin / mpn",
          "value": "missing",
          "status": "warn"
        },
        {
          "label": "brand",
          "value": "missing",
          "status": "warn"
        },
        {
          "label": "shippingDetails",
          "value": "missing",
          "status": "warn"
        },
        {
          "label": "hasMerchantReturnPolicy",
          "value": "missing",
          "status": "warn"
        },
        {
          "label": "aggregateRating",
          "value": "missing",
          "status": "warn"
        }
      ],
      "fix": {
        "summary": "Add the missing Product fields. The template below is pre-filled with what Legible found.",
        "steps": [
          "WooCommerce outputs basic Product JSON-LD on its own. Fill the native \"GTIN, UPC, EAN or ISBN\" field (Inventory tab, WooCommerce 9.2+) and a brand for every product.",
          "Shipping and return details are not in the default markup: add them through your SEO plugin's schema settings or a small snippet hooked to woocommerce_structured_data_product.",
          "Avoid two plugins both printing Product schema: duplicates with different prices confuse agents."
        ],
        "snippet": {
          "language": "html",
          "filename": "Product JSON-LD (product template)",
          "code": "<!-- Product JSON-LD generated by Legible from this page.\n     Replace every REPLACE_… value, then check delivery times, the 14-day\n     return window and return fees against your real policy before publishing.\n     Add aggregateRating only if the page shows real customer reviews. -->\n<script type=\"application/ld+json\">\n{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"Product\",\n  \"name\": \"Ethiopia Guji Natural\",\n  \"description\": \"Natural process coffee from the Guji zone. Notes of blueberry, dark chocolate and jasmine. 250 g whole bean.\",\n  \"image\": [\n    \"https://hollowoak.example/wp-content/uploads/2026/09/guji.jpg\"\n  ],\n  \"sku\": \"HO-GUJI-250\",\n  \"gtin\": \"REPLACE_BARCODE_OR_DELETE_THIS_LINE\",\n  \"brand\": {\n    \"@type\": \"Brand\",\n    \"name\": \"Hollow Oak Coffee Roasters\"\n  },\n  \"offers\": {\n    \"@type\": \"Offer\",\n    \"url\": \"https://hollowoak.example/product/ethiopia-guji-natural/\",\n    \"price\": \"16.50\",\n    \"priceCurrency\": \"EUR\",\n    \"availability\": \"https://schema.org/InStock\",\n    \"itemCondition\": \"https://schema.org/NewCondition\",\n    \"seller\": {\n      \"@type\": \"Organization\",\n      \"name\": \"Hollow Oak Coffee Roasters\"\n    },\n    \"shippingDetails\": {\n      \"@type\": \"OfferShippingDetails\",\n      \"shippingRate\": {\n        \"@type\": \"MonetaryAmount\",\n        \"value\": \"REPLACE_SHIPPING_COST\",\n        \"currency\": \"EUR\"\n      },\n      \"shippingDestination\": {\n        \"@type\": \"DefinedRegion\",\n        \"addressCountry\": \"REPLACE_COUNTRY_CODE\"\n      },\n      \"deliveryTime\": {\n        \"@type\": \"ShippingDeliveryTime\",\n        \"handlingTime\": {\n          \"@type\": \"QuantitativeValue\",\n          \"minValue\": 0,\n          \"maxValue\": 1,\n          \"unitCode\": \"DAY\"\n        },\n        \"transitTime\": {\n          \"@type\": \"QuantitativeValue\",\n          \"minValue\": 1,\n          \"maxValue\": 3,\n          \"unitCode\": \"DAY\"\n        }\n      }\n    },\n    \"hasMerchantReturnPolicy\": {\n      \"@type\": \"MerchantReturnPolicy\",\n      \"applicableCountry\": \"REPLACE_COUNTRY_CODE\",\n      \"returnPolicyCategory\": \"https://schema.org/MerchantReturnFiniteReturnWindow\",\n      \"merchantReturnDays\": 14,\n      \"returnMethod\": \"https://schema.org/ReturnByMail\",\n      \"returnFees\": \"https://schema.org/ReturnShippingFees\"\n    }\n  }\n}\n</script>"
        }
      }
    },
    {
      "id": "understanding.site-schema",
      "pillar": "understanding",
      "title": "Organization and WebSite schema",
      "weight": 2,
      "why": "Organization and WebSite markup tells an agent the store's official name, logo, URL and social profiles, so it can tell your shop apart from resellers and lookalikes.",
      "status": "pass",
      "score": 1,
      "summary": "Organization and WebSite schema identify the store as \"Hollow Oak Coffee Roasters\".",
      "evidence": [
        {
          "label": "Organization",
          "value": "Hollow Oak Coffee Roasters",
          "status": "pass"
        },
        {
          "label": "WebSite",
          "value": "Hollow Oak Coffee Roasters",
          "status": "pass"
        },
        {
          "label": "logo",
          "value": "present",
          "status": "pass"
        },
        {
          "label": "sameAs",
          "value": "missing",
          "status": "warn"
        }
      ]
    },
    {
      "id": "understanding.opengraph",
      "pillar": "understanding",
      "title": "OpenGraph product preview",
      "weight": 1,
      "why": "Chat interfaces render link previews and many agents fall back to OpenGraph when JSON-LD is missing. og:title, og:image and og:type are the minimum.",
      "status": "fail",
      "score": 0,
      "summary": "OpenGraph is mostly missing (og:description, og:image and og:type).",
      "evidence": [
        {
          "label": "og:title",
          "value": "Ethiopia Guji Natural - Hollow Oak Coffee Roasters",
          "status": "pass"
        },
        {
          "label": "og:description",
          "value": "missing",
          "status": "warn"
        },
        {
          "label": "og:image",
          "value": "missing",
          "status": "warn"
        },
        {
          "label": "og:url",
          "value": "https://hollowoak.example/product/ethiopia-guji-natural/",
          "status": "pass"
        },
        {
          "label": "og:type",
          "value": "missing",
          "status": "warn"
        }
      ],
      "fix": {
        "summary": "Add og:description, og:image and og:type to the product template."
      }
    },
    {
      "id": "understanding.canonical-lang",
      "pillar": "understanding",
      "title": "Canonical URL and language",
      "weight": 1,
      "why": "A canonical URL collapses filter and tracking variants into one product, and a lang attribute tells the agent which language and market the price and policies apply to.",
      "status": "pass",
      "score": 1,
      "summary": "Canonical set, language en-US.",
      "evidence": [
        {
          "label": "canonical",
          "value": "https://hollowoak.example/product/ethiopia-guji-natural/",
          "status": "pass"
        },
        {
          "label": "html lang",
          "value": "en-US",
          "status": "pass"
        }
      ]
    },
    {
      "id": "understanding.headings",
      "pillar": "understanding",
      "title": "One clear H1 with the product name",
      "weight": 1,
      "why": "Extractors use the heading outline to split a page into sections. One H1 naming the product, then H2s for details and reviews, makes the page easy to chunk.",
      "status": "warn",
      "score": 0.5,
      "summary": "2 H1 headings. The product name should be the only one.",
      "evidence": [
        {
          "label": "H1",
          "value": "Hollow Oak Coffee Roasters | Ethiopia Guji Natural",
          "status": "warn"
        },
        {
          "label": "H2",
          "value": "3"
        }
      ],
      "fix": {
        "summary": "Demote logo and section titles to other elements; keep one <h1> for the product."
      }
    },
    {
      "id": "understanding.llms-txt",
      "pillar": "understanding",
      "title": "llms.txt guide for agents",
      "weight": 1,
      "why": "llms.txt is a proposed markdown index of a site's most useful pages. No major assistant has confirmed it uses the file, so it carries little weight here, but it is cheap and gives agents a clean map of products and policies.",
      "status": "warn",
      "score": 0.5,
      "summary": "No llms.txt found.",
      "evidence": [
        {
          "label": "llms-full.txt",
          "value": "not found"
        }
      ],
      "fix": {
        "summary": "Publish /llms.txt. This one is generated from the pages Legible found on your site.",
        "steps": [
          "Upload llms.txt to the WordPress root (next to wp-config.php), or use an SEO plugin that generates one (Yoast and Rank Math both offer llms.txt generation)."
        ],
        "snippet": {
          "language": "markdown",
          "filename": "/llms.txt",
          "code": "# Hollow Oak Coffee Roasters\n\n> Specialty coffee roasted weekly in Zagreb. Single origins and blends, shipped across Croatia and the EU.\n\n## Products\n\n- [Ethiopia Guji Natural](https://hollowoak.example/product/ethiopia-guji-natural/)\n- [Colombia Huila Washed](https://hollowoak.example/product/colombia-huila-washed/)\n- [Oak House Espresso](https://hollowoak.example/product/oak-house-espresso/)\n\n## Categories\n\n- [Shop](https://hollowoak.example/shop/)\n- [Single origin](https://hollowoak.example/product-category/single-origin/)\n- [Blends](https://hollowoak.example/product-category/blends/)\n\n## Policies\n\n- [Privacy Policy](https://hollowoak.example/privacy-policy/)\n- [Terms & Conditions](https://hollowoak.example/terms-and-conditions/)\n- [Contact](https://hollowoak.example/contact/)\n\n## Optional\n\n- [Our story](https://hollowoak.example/our-story/)\n"
        }
      }
    },
    {
      "id": "trust.https",
      "pillar": "trust",
      "title": "HTTPS everywhere, with HSTS",
      "weight": 3,
      "why": "Agents that hand a shopper off to checkout will not send them to an insecure page. HSTS proves the store never falls back to plain HTTP.",
      "status": "warn",
      "score": 0.5,
      "summary": "HTTPS works, but no HSTS header is sent.",
      "evidence": [
        {
          "label": "Final URL scheme",
          "value": "https",
          "status": "pass"
        },
        {
          "label": "http:// redirects to https",
          "value": "yes (301)",
          "status": "pass"
        },
        {
          "label": "Strict-Transport-Security",
          "value": "not sent",
          "status": "warn"
        }
      ],
      "fix": {
        "summary": "Send an HSTS header.",
        "steps": [
          "Add the Strict-Transport-Security header at the web server or CDN; security plugins such as Really Simple SSL can also add it."
        ],
        "snippet": {
          "language": "txt",
          "filename": "Response header",
          "code": "Strict-Transport-Security: max-age=31536000"
        }
      }
    },
    {
      "id": "trust.policies",
      "pillar": "trust",
      "title": "Policy pages are linked",
      "weight": 4,
      "why": "Before recommending a purchase, assistants look for shipping costs, the return window and who to contact. In the EU, consumers have a 14-day right of withdrawal for most online purchases (Directive 2011/83/EU, Art. 9), so returns terms are a deciding fact.",
      "status": "fail",
      "score": 0.3,
      "summary": "No shipping and returns page is linked from the homepage or product page.",
      "evidence": [
        {
          "label": "Shipping",
          "value": "no link found",
          "status": "fail"
        },
        {
          "label": "Returns",
          "value": "no link found",
          "status": "fail"
        },
        {
          "label": "Privacy",
          "value": "https://hollowoak.example/privacy-policy/",
          "status": "pass"
        },
        {
          "label": "Terms",
          "value": "https://hollowoak.example/terms-and-conditions/",
          "status": "pass"
        },
        {
          "label": "Contact",
          "value": "https://hollowoak.example/contact/",
          "status": "pass"
        }
      ],
      "fix": {
        "summary": "Link shipping and returns from the site footer.",
        "steps": [
          "Link shipping, returns, privacy and terms pages in the footer menu (Appearance → Menus or the Site Editor footer). Set the Terms page under WooCommerce → Settings → Advanced."
        ]
      }
    },
    {
      "id": "trust.identity",
      "pillar": "trust",
      "title": "Business identity is machine-readable",
      "weight": 3,
      "why": "Agents weigh whether a merchant is real. A legal name, postal address and a contact point in Organization schema are the strongest signals short of a marketplace listing.",
      "status": "warn",
      "score": 0.5,
      "summary": "Organization schema found, but address, contact details and legal name or VAT ID are missing.",
      "evidence": [
        {
          "label": "address",
          "value": "missing",
          "status": "fail"
        },
        {
          "label": "email / telephone / contactPoint",
          "value": "missing",
          "status": "fail"
        },
        {
          "label": "legalName / vatID",
          "value": "missing",
          "status": "warn"
        }
      ],
      "fix": {
        "summary": "Add address, contact details and legal name or VAT ID to the Organization node."
      }
    },
    {
      "id": "trust.price-consistency",
      "pillar": "trust",
      "title": "Visible price matches structured data",
      "weight": 4,
      "why": "When the price a shopper sees differs from the price in JSON-LD, agents quote the wrong number or distrust both. Google Merchant Center suspends listings for mismatches, and under EU consumer law the price shown must be the price charged.",
      "status": "fail",
      "score": 0,
      "summary": "JSON-LD still says EUR 16.50, the struck-through regular price. Shoppers see 14.90. Agents will quote the higher price.",
      "evidence": [
        {
          "label": "JSON-LD price",
          "value": "EUR 16.50"
        },
        {
          "label": "Current prices on page",
          "value": "14.90"
        },
        {
          "label": "Struck-through prices",
          "value": "16.50"
        },
        {
          "label": "Microdata price",
          "value": "none"
        }
      ],
      "fix": {
        "summary": "Generate JSON-LD from the same price the template displays, including sale prices.",
        "steps": [
          "Typical cause: a caching or SEO plugin prints the regular price while the theme shows the sale price. Purge caches after price changes and keep one schema source."
        ]
      }
    },
    {
      "id": "transaction.ucp",
      "pillar": "transaction",
      "title": "UCP business profile",
      "weight": 5,
      "why": "The Universal Commerce Protocol (UCP), announced by Google in January 2026, lets agents discover a store's capabilities from /.well-known/ucp and complete checkout through a standard API. It powers buying in Google AI Mode and Gemini. Current spec version: 2026-08-25.",
      "status": "fail",
      "score": 0,
      "summary": "No UCP profile at /.well-known/ucp, so agents cannot discover a checkout. Few WooCommerce stores publish one yet.",
      "fix": {
        "summary": "Publish a UCP profile backed by a working checkout implementation.",
        "steps": [
          "Several WordPress.org plugins now publish a UCP profile and checkout endpoints for WooCommerce (search the directory for \"Universal Commerce Protocol\"). Test any of them on staging first: they take part in checkout.",
          "Whatever you install, confirm /.well-known/ucp returns valid JSON with a dev.ucp.shopping.checkout capability."
        ],
        "snippet": {
          "language": "json",
          "filename": "/.well-known/ucp (skeleton)",
          "code": "{\n  \"ucp\": {\n    \"version\": \"2026-08-25\",\n    \"services\": {\n      \"dev.ucp.shopping\": [\n        {\n          \"version\": \"2026-08-25\",\n          \"spec\": \"https://ucp.dev/2026-08-25/specification/overview/\",\n          \"transport\": \"rest\",\n          \"endpoint\": \"https://hollowoak.example/ucp/v1\",\n          \"schema\": \"https://ucp.dev/2026-08-25/services/shopping/rest.openapi.json\"\n        }\n      ]\n    },\n    \"capabilities\": {\n      \"dev.ucp.shopping.checkout\": [\n        {\n          \"version\": \"2026-08-25\",\n          \"spec\": \"https://ucp.dev/2026-08-25/specification/shopping/checkout/\",\n          \"schema\": \"https://ucp.dev/2026-08-25/schemas/shopping/checkout.json\"\n        }\n      ],\n      \"dev.ucp.shopping.fulfillment\": [\n        {\n          \"version\": \"2026-08-25\",\n          \"spec\": \"https://ucp.dev/2026-08-25/specification/shopping/extensions/fulfillment/\",\n          \"schema\": \"https://ucp.dev/2026-08-25/schemas/shopping/fulfillment.json\",\n          \"extends\": \"dev.ucp.shopping.checkout\"\n        }\n      ]\n    },\n    \"payment_handlers\": {}\n  },\n  \"keys\": []\n}"
        }
      }
    },
    {
      "id": "transaction.catalogue",
      "pillar": "transaction",
      "title": "Machine-readable catalogue",
      "weight": 3,
      "why": "Agent channels (ChatGPT shopping, Google AI Mode, Copilot) prefer a structured product feed they can refresh over crawling pages. A feed keeps price and stock current between crawls.",
      "status": "pass",
      "score": 1,
      "summary": "2 catalogue signals detected.",
      "evidence": [
        {
          "label": "Signal",
          "value": "WooCommerce Store API (/wp-json/wc/store/v1/products, on by default)",
          "status": "pass"
        },
        {
          "label": "Signal",
          "value": "Product sitemap (6 URLs)",
          "status": "pass"
        }
      ],
      "fix": {
        "summary": "Expose a product feed and submit it to agent channels.",
        "steps": [
          "The WooCommerce Store API (/wp-json/wc/store/v1/products) is public by default unless a plugin disables it: it is a ready-made product feed.",
          "For ChatGPT, merchants apply through OpenAI's merchant program and submit a product feed; for Google AI Mode, connect Google Merchant Center with the \"Google for WooCommerce\" extension."
        ]
      }
    },
    {
      "id": "transaction.acp",
      "pillar": "transaction",
      "title": "Agentic Commerce Protocol readiness (signal)",
      "weight": 1,
      "why": "OpenAI and Stripe's Agentic Commerce Protocol (ACP) launched in September 2025 to let shoppers buy inside ChatGPT. There is no public discovery file: merchants are onboarded through OpenAI and submit a product feed. In March 2026 OpenAI moved checkout back to merchants' own sites, so discovery in ChatGPT now depends on that feed and on crawlable pages. Legible scores the prerequisites, not enrolment.",
      "status": "warn",
      "score": 0.6666666666666666,
      "summary": "2 of 3 ACP prerequisites in place.",
      "evidence": [
        {
          "label": "OAI-SearchBot allowed",
          "value": "no",
          "status": "fail"
        },
        {
          "label": "Product structured data",
          "value": "yes",
          "status": "pass"
        },
        {
          "label": "Feed source available",
          "value": "yes",
          "status": "pass"
        }
      ],
      "fix": {
        "summary": "Apply to OpenAI's merchant program and submit a product feed.",
        "steps": [
          "Merchants apply at chatgpt.com/merchants. Shopify and Etsy merchants are onboarded through their platform.",
          "The WooCommerce Store API (/wp-json/wc/store/v1/products) is public by default unless a plugin disables it: it is a ready-made product feed.",
          "For ChatGPT, merchants apply through OpenAI's merchant program and submit a product feed; for Google AI Mode, connect Google Merchant Center with the \"Google for WooCommerce\" extension."
        ]
      }
    },
    {
      "id": "transaction.cart-path",
      "pillar": "transaction",
      "title": "Add-to-cart works without scripts",
      "weight": 2,
      "why": "Browser-driving agents (ChatGPT agent, Gemini in Chrome and similar) click through your real checkout. A plain form or link for add-to-cart in the server HTML is the most robust path when no protocol is available.",
      "status": "pass",
      "score": 1,
      "summary": "The product page has a server-rendered add-to-cart form or link.",
      "evidence": [
        {
          "label": "Cart form in HTML",
          "value": "yes",
          "status": "pass"
        },
        {
          "label": "Add-to-cart link",
          "value": "no"
        },
        {
          "label": "Add-to-cart button",
          "value": "yes",
          "status": "pass"
        }
      ]
    },
    {
      "id": "transaction.platform",
      "pillar": "transaction",
      "title": "Platform and remediation path",
      "weight": 0,
      "why": "What you can fix, and how fast, depends on the platform. Shopify merchants can switch most of this on; WooCommerce, Magento and custom stores need it built or configured.",
      "status": "info",
      "score": null,
      "summary": "Detected WooCommerce (high confidence).",
      "evidence": [
        {
          "label": "Signal",
          "value": "WooCommerce generator meta tag"
        },
        {
          "label": "Signal",
          "value": "/wp-content/plugins/woocommerce/ assets"
        },
        {
          "label": "Signal",
          "value": "woocommerce body or element classes"
        },
        {
          "label": "Signal",
          "value": "WordPress REST API header"
        }
      ],
      "fix": {
        "summary": "Fix order for WooCommerce:",
        "steps": [
          "If an SEO plugin (Yoast, Rank Math, AIOSEO) manages robots.txt, edit it there: Yoast → Tools → File editor; Rank Math → General Settings → Edit robots.txt.",
          "WooCommerce outputs basic Product JSON-LD on its own. Fill the native \"GTIN, UPC, EAN or ISBN\" field (Inventory tab, WooCommerce 9.2+) and a brand for every product.",
          "Several WordPress.org plugins now publish a UCP profile and checkout endpoints for WooCommerce (search the directory for \"Universal Commerce Protocol\"). Test any of them on staging first: they take part in checkout."
        ]
      }
    }
  ],
  "agentView": {
    "url": "https://hollowoak.example/product/ethiopia-guji-natural/",
    "rawExcerpt": "<header class=\"site-header\">\n<h1 class=\"site-title\">\n<a href=\"https://hollowoak.example/\">Hollow Oak Coffee Roasters</a>\n</h1>\n<nav class=\"main-navigation\" aria-label=\"Primary\">\n<ul>\n<li>\n<a href=\"https://hollowoak.example/shop/\">Shop</a>\n</li>\n<li>\n<a href=\"https://hollowoak.example/product-category/single-origin/\">Single origin</a>\n</li>\n<li>\n<a href=\"https://hollowoak.example/product-category/blends/\">Blends</a>\n</li>\n<li>\n<a href=\"https://hollowoak.example/our-story/\">Our story</a>\n</li>\n<li>\n<a href=\"https://hollowoak.example/cart/\">Cart</a>\n</li>\n</ul>\n</nav>\n</header>\n<main id=\"primary\" class=\"site-main\">\n<nav class=\"woocommerce-breadcrumb\" aria-label=\"Breadcrumb\">\n<a href=\"https://hollowoak.example/\">Home</a> / <a href=\"https://hollowoak.example/product-category/single-origin/\">Single origin</a> / Ethiopia Guji Natural</nav>\n<div id=\"product-412\" class=\"product type-product status-publish instock product_cat-single-origin sale\">\n<div class=\"woocommerce-product-gallery\">\n<img src=\"https://hollowoak.example/wp-content/uploads/2026/09/guji.jpg\" alt=\"\">\n</div>\n<div class=\"summary entry-summary\">\n<h1 class=\"product_title entry-title\">Ethiopia Guji Natural</h1>\n<p class=\"price\">\n<del aria-hidden=\"true\">\n<span class=\"woocommerce-Price-amount amount\">\n<bdi>16,50&nbsp;<span class=\"woocommerce-Price-currencySymbol\">&euro;</span>\n</bdi>\n</span>\n</del>\n<span class=\"screen-reader-text\">Original price was: 16,50&nbsp;&euro;.</span>\n<ins aria-hidden=\"true\">\n<span class=\"woocommerce-Price-amount amount\">\n<bdi>14,90&nbsp;<span class=\"woocommerce-Price-currencySymbol\">&euro;</span>\n</bdi>\n</span>\n</ins>\n<span class=\"screen-reader-text\">Current price is: 14,90&nbsp;&euro;.</span>\n</p>\n<div class=\"woocommerce-product-details__short-description\">\n<p>Natural process coffee from the Guji zone in southern Ethiopia, grown at 2,100 metres. Expect blueberry, dark chocolate and jasmine. 250 g whole bean, roasted for filter and espresso.</p>\n</div>\n<p class=\"stock in-stock\">14 in stock</p>\n<form class=\"cart\" action=\"https://hollowoak.example/product/ethiopia-guji-natural/\" method=\"post\" enctype='multipart/form-data'>\n<div class=\"quantity\">\n<label class=\"screen-reader-text\" for=\"quantity_1\">Ethiopia Guji Natural quantity</label>\n<input type=\"number\" id=\"quantity_1\" class=\"input-text qty text\" name=\"quantity\" value=\"1\" min=\"1\" max=\"14\" step=\"1\">\n</div>\n<button type=\"submit\" name=\"add-to-cart\" value=\"412\" class=\"single_add_to_cart_button button alt\">Add to cart</button>\n</form>\n<div class=\"product_meta\">\n<span class=\"sku_wrapper\">SKU: <span class=\"sku\">HO-GUJI-250</span>\n</span\n<!-- … 2 KB more -->",
    "markdown": "# Ethiopia Guji Natural\n\n16,50 € Original price was: 16,50 €.14,90 €Current price is: 14,90 €.\n\nNatural process coffee from the Guji zone in southern Ethiopia, grown at 2,100 metres. Expect blueberry, dark chocolate and jasmine. 250 g whole bean, roasted for filter and espresso.\n\n14 in stock\n\nSKU: HO-GUJI-250 Category:  [Single origin](https://hollowoak.example/product-category/single-origin/)\n\n## Description\n\nGuji coffees are dried whole in the cherry on raised beds for three to four weeks. The slow drying gives a heavy body and intense fruit. We roast this lot light to medium to keep the florals.\n\nBrew ratio we like: 15 g coffee to 250 g water, 93°C, three and a half minutes.\n\n## Additional information\n\n| Weight | 0.25 kg |\n| --- | --- |\n| Process | Natural |\n| Altitude | 2,100 m |\n\n## Related products\n\n- [Colombia Huila Washed](https://hollowoak.example/product/colombia-huila-washed/)\n- [Oak House Espresso](https://hollowoak.example/product/oak-house-espresso/)",
    "tokens": 245,
    "htmlBytes": 7184,
    "facts": [
      {
        "label": "Product name",
        "value": "Ethiopia Guji Natural",
        "source": "both"
      },
      {
        "label": "Price",
        "value": "EUR 16.50",
        "source": "both"
      },
      {
        "label": "Availability",
        "value": "InStock",
        "source": "both"
      },
      {
        "label": "Brand",
        "value": null,
        "source": null
      },
      {
        "label": "GTIN / EAN",
        "value": null,
        "source": null
      },
      {
        "label": "Shipping",
        "value": null,
        "source": null
      },
      {
        "label": "Returns",
        "value": null,
        "source": null
      },
      {
        "label": "Rating",
        "value": null,
        "source": null
      }
    ]
  },
  "fetchLog": [
    {
      "url": "https://hollowoak.example/",
      "purpose": "Homepage (as LegibleBot)",
      "status": 200,
      "ms": 1400,
      "bytes": 15070
    },
    {
      "url": "https://hollowoak.example/",
      "purpose": "Homepage (as a browser, for bot-wall comparison)",
      "status": 200,
      "ms": 1400,
      "bytes": 15070
    },
    {
      "url": "https://hollowoak.example/robots.txt",
      "purpose": "robots.txt",
      "status": 200,
      "ms": 230,
      "bytes": 490
    },
    {
      "url": "http://hollowoak.example/",
      "purpose": "HTTP to HTTPS redirect probe",
      "status": 301,
      "ms": 110,
      "bytes": 0
    },
    {
      "url": "https://hollowoak.example/llms.txt",
      "purpose": "llms.txt",
      "status": 404,
      "ms": 1000,
      "bytes": 2763
    },
    {
      "url": "https://hollowoak.example/llms-full.txt",
      "purpose": "llms-full.txt",
      "status": 404,
      "ms": 1000,
      "bytes": 2763
    },
    {
      "url": "https://hollowoak.example/.well-known/ucp",
      "purpose": "UCP business profile",
      "status": 404,
      "ms": 1000,
      "bytes": 2763
    },
    {
      "url": "https://hollowoak.example/sitemap_index.xml",
      "purpose": "XML sitemap",
      "status": 200,
      "ms": 660,
      "bytes": 677
    },
    {
      "url": "https://hollowoak.example/product-sitemap.xml",
      "purpose": "Product sitemap",
      "status": 200,
      "ms": 610,
      "bytes": 764
    },
    {
      "url": "https://hollowoak.example/product/ethiopia-guji-natural/",
      "purpose": "Product page (as LegibleBot)",
      "status": 200,
      "ms": 1740,
      "bytes": 7184
    }
  ],
  "protocols": {
    "ucp": "2026-08-25",
    "robotsAgents": "2026-10-07"
  }
}