{
  "schema": 1,
  "id": "demo-kestrel-pine",
  "url": "https://kestrelpine.example/",
  "host": "kestrelpine.example",
  "productUrl": "https://kestrelpine.example/products/alpine-merino-hoodie",
  "scannedAt": "2026-10-06T09:14:00.000Z",
  "durationMs": 1400,
  "demo": true,
  "siteName": "Kestrel & Pine",
  "platform": {
    "platform": "shopify",
    "confidence": "high",
    "signals": [
      "cdn.shopify.com assets",
      "Shopify global object",
      "x-shopid / powered-by Shopify header"
    ]
  },
  "score": 98,
  "rawScore": 98,
  "cap": null,
  "grade": "A",
  "pillars": [
    {
      "pillar": "access",
      "score": 95,
      "counts": {
        "pass": 7,
        "warn": 1,
        "fail": 0,
        "info": 1
      }
    },
    {
      "pillar": "understanding",
      "score": 100,
      "counts": {
        "pass": 7,
        "warn": 0,
        "fail": 0,
        "info": 0
      }
    },
    {
      "pillar": "trust",
      "score": 100,
      "counts": {
        "pass": 4,
        "warn": 0,
        "fail": 0,
        "info": 0
      }
    },
    {
      "pillar": "transaction",
      "score": 95,
      "counts": {
        "pass": 4,
        "warn": 0,
        "fail": 0,
        "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://kestrelpine.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": "pass",
      "score": 1,
      "summary": "Every AI search and user-triggered agent may fetch the homepage and the product page.",
      "evidence": [
        {
          "label": "OAI-SearchBot (OpenAI)",
          "value": "Allowed",
          "status": "pass"
        },
        {
          "label": "ChatGPT-User (OpenAI)",
          "value": "Allowed",
          "status": "pass"
        },
        {
          "label": "Claude-SearchBot (Anthropic)",
          "value": "Allowed",
          "status": "pass"
        },
        {
          "label": "Claude-User (Anthropic)",
          "value": "Allowed",
          "status": "pass"
        },
        {
          "label": "PerplexityBot (Perplexity)",
          "value": "Allowed",
          "status": "pass"
        },
        {
          "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"
        }
      ]
    },
    {
      "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": "5 training crawlers blocked, 3 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": "Allowed"
        },
        {
          "label": "meta-externalagent (Meta)",
          "value": "Allowed"
        },
        {
          "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: 3 groups, 1 sitemap.",
      "evidence": [
        {
          "label": "Groups",
          "value": "3"
        },
        {
          "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 8 product URLs.",
      "evidence": [
        {
          "label": "Location",
          "value": "https://kestrelpine.example/sitemap.xml"
        },
        {
          "label": "Found via",
          "value": "robots.txt"
        },
        {
          "label": "Type",
          "value": "Sitemap index (4 child sitemaps)"
        },
        {
          "label": "Product sitemap",
          "value": "https://kestrelpine.example/sitemap_products_1.xml?from=1&to=99 (8 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": "warn",
      "score": 0.5,
      "summary": "Slowest time to first byte: 690 ms. Aim for under 600 ms.",
      "evidence": [
        {
          "label": "/",
          "value": "182 ms",
          "status": "pass"
        },
        {
          "label": "/products/alpine-merino-hoodie",
          "value": "690 ms",
          "status": "warn"
        }
      ],
      "fix": {
        "summary": "Cache full HTML pages so they are served without hitting the application.",
        "steps": [
          "Shopify serves HTML from its CDN. Slow TTFB usually means heavy Liquid loops or apps injecting server-side content: audit apps."
        ]
      }
    },
    {
      "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": "6 KB of HTML for /products/alpine-merino-hoodie.",
      "evidence": [
        {
          "label": "HTML size",
          "value": "6 KB"
        },
        {
          "label": "Inline script",
          "value": "0 KB in 2 tags"
        },
        {
          "label": "Visible words",
          "value": "147"
        }
      ]
    },
    {
      "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 147 words of content are in the server HTML.",
      "evidence": [
        {
          "label": "Visible words (no JS)",
          "value": "147",
          "status": "pass"
        },
        {
          "label": "Product name in text",
          "value": "Yes",
          "status": "pass"
        },
        {
          "label": "Price in text",
          "value": "129.00",
          "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": "pass",
      "score": 1,
      "summary": "Product schema is 100% complete.",
      "evidence": [
        {
          "label": "name",
          "value": "Alpine Merino Hoodie",
          "status": "pass"
        },
        {
          "label": "image",
          "value": "https://kestrelpine.example/cdn/shop/files/alpine-merino-hoodie-moss.jpg",
          "status": "pass"
        },
        {
          "label": "description",
          "value": "A 260 g/m² merino wool hoodie with a scuba hood, flatlock seams and thumb loops.",
          "status": "pass"
        },
        {
          "label": "offers.price",
          "value": "129",
          "status": "pass"
        },
        {
          "label": "offers.priceCurrency",
          "value": "EUR",
          "status": "pass"
        },
        {
          "label": "offers.availability",
          "value": "https://schema.org/InStock",
          "status": "pass"
        },
        {
          "label": "sku",
          "value": "KP-AMH-MOSS-M",
          "status": "pass"
        },
        {
          "label": "gtin / mpn",
          "value": "3856012345678",
          "status": "pass"
        },
        {
          "label": "brand",
          "value": "Kestrel & Pine",
          "status": "pass"
        },
        {
          "label": "shippingDetails",
          "value": "present",
          "status": "pass"
        },
        {
          "label": "hasMerchantReturnPolicy",
          "value": "present",
          "status": "pass"
        },
        {
          "label": "aggregateRating",
          "value": "present",
          "status": "pass"
        }
      ]
    },
    {
      "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 \"Kestrel & Pine\".",
      "evidence": [
        {
          "label": "Organization",
          "value": "Kestrel & Pine",
          "status": "pass"
        },
        {
          "label": "WebSite",
          "value": "Kestrel & Pine",
          "status": "pass"
        },
        {
          "label": "logo",
          "value": "present",
          "status": "pass"
        },
        {
          "label": "sameAs",
          "value": "present",
          "status": "pass"
        }
      ]
    },
    {
      "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": "pass",
      "score": 1,
      "summary": "Complete OpenGraph (og:type product).",
      "evidence": [
        {
          "label": "og:title",
          "value": "Alpine Merino Hoodie",
          "status": "pass"
        },
        {
          "label": "og:description",
          "value": "260 g/m² merino hoodie with scuba hood and thumb loops.",
          "status": "pass"
        },
        {
          "label": "og:image",
          "value": "https://kestrelpine.example/cdn/shop/files/alpine-merino-hoodie-moss.jpg",
          "status": "pass"
        },
        {
          "label": "og:url",
          "value": "https://kestrelpine.example/products/alpine-merino-hoodie",
          "status": "pass"
        },
        {
          "label": "og:type",
          "value": "product",
          "status": "pass"
        }
      ]
    },
    {
      "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.",
      "evidence": [
        {
          "label": "canonical",
          "value": "https://kestrelpine.example/products/alpine-merino-hoodie",
          "status": "pass"
        },
        {
          "label": "html lang",
          "value": "en",
          "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": "pass",
      "score": 1,
      "summary": "H1 \"Alpine Merino Hoodie\" with 3 H2 sections.",
      "evidence": [
        {
          "label": "H1",
          "value": "Alpine Merino Hoodie",
          "status": "pass"
        },
        {
          "label": "H2",
          "value": "3"
        }
      ]
    },
    {
      "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": "pass",
      "score": 1,
      "summary": "Valid llms.txt with 3 sections and 7 links.",
      "evidence": [
        {
          "label": "Title",
          "value": "Kestrel & Pine",
          "status": "pass"
        },
        {
          "label": "Summary blockquote",
          "value": "present",
          "status": "pass"
        },
        {
          "label": "Sections",
          "value": "Products, Policies, Optional"
        },
        {
          "label": "Links",
          "value": "7"
        },
        {
          "label": "llms-full.txt",
          "value": "not found"
        }
      ]
    },
    {
      "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": "pass",
      "score": 1,
      "summary": "HTTPS with HSTS, and HTTP redirects to HTTPS.",
      "evidence": [
        {
          "label": "Final URL scheme",
          "value": "https",
          "status": "pass"
        },
        {
          "label": "http:// redirects to https",
          "value": "yes (301)",
          "status": "pass"
        },
        {
          "label": "Strict-Transport-Security",
          "value": "max-age=31536000; includeSubDomains",
          "status": "pass"
        }
      ]
    },
    {
      "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": "pass",
      "score": 1,
      "summary": "Shipping, returns, privacy, terms and contact pages are all linked.",
      "evidence": [
        {
          "label": "Shipping",
          "value": "https://kestrelpine.example/policies/shipping-policy",
          "status": "pass"
        },
        {
          "label": "Returns",
          "value": "https://kestrelpine.example/policies/refund-policy",
          "status": "pass"
        },
        {
          "label": "Privacy",
          "value": "https://kestrelpine.example/policies/privacy-policy",
          "status": "pass"
        },
        {
          "label": "Terms",
          "value": "https://kestrelpine.example/policies/terms-of-service",
          "status": "pass"
        },
        {
          "label": "Contact",
          "value": "https://kestrelpine.example/pages/contact",
          "status": "pass"
        }
      ]
    },
    {
      "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": "pass",
      "score": 1,
      "summary": "Legal identity, address and contact details are all machine-readable.",
      "evidence": [
        {
          "label": "address",
          "value": "present",
          "status": "pass"
        },
        {
          "label": "email / telephone / contactPoint",
          "value": "present",
          "status": "pass"
        },
        {
          "label": "legalName / vatID",
          "value": "present",
          "status": "pass"
        }
      ]
    },
    {
      "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": "pass",
      "score": 1,
      "summary": "The visible price and JSON-LD agree on EUR 129.00.",
      "evidence": [
        {
          "label": "JSON-LD price",
          "value": "EUR 129.00"
        },
        {
          "label": "Current prices on page",
          "value": "129.00"
        },
        {
          "label": "Microdata price",
          "value": "none"
        }
      ]
    },
    {
      "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": "pass",
      "score": 0.9,
      "summary": "Valid UCP profile (2026-08-25) with checkout. 1 suggestion.",
      "evidence": [
        {
          "label": "ucp.version",
          "value": "2026-08-25",
          "status": "pass"
        },
        {
          "label": "Services",
          "value": "dev.ucp.shopping"
        },
        {
          "label": "Transports",
          "value": "rest, mcp"
        },
        {
          "label": "Capabilities",
          "value": "Checkout, Cart, Fulfillment (extension), Orders",
          "status": "pass"
        },
        {
          "label": "Payment handlers",
          "value": "declared"
        },
        {
          "label": "Signing keys",
          "value": "none"
        },
        {
          "label": "$.keys",
          "value": "No signing keys published. Recommended so agents can verify signed responses.",
          "status": "warn"
        }
      ]
    },
    {
      "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": "Shopify catalogue (syncable to agent channels through Agentic Storefronts)",
          "status": "pass"
        },
        {
          "label": "Signal",
          "value": "Product sitemap (8 URLs)",
          "status": "pass"
        }
      ],
      "fix": {
        "summary": "Expose a product feed and submit it to agent channels.",
        "steps": [
          "Shopify syncs the catalogue to agent channels through Agentic Storefronts and the Google & YouTube app."
        ]
      }
    },
    {
      "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": "pass",
      "score": 1,
      "summary": "All ACP prerequisites are in place. Enrolment itself happens with OpenAI and cannot be detected from outside.",
      "evidence": [
        {
          "label": "OAI-SearchBot allowed",
          "value": "yes",
          "status": "pass"
        },
        {
          "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.",
          "Shopify syncs the catalogue to agent channels through Agentic Storefronts and the Google & YouTube app."
        ]
      }
    },
    {
      "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 Shopify (high confidence).",
      "evidence": [
        {
          "label": "Signal",
          "value": "cdn.shopify.com assets"
        },
        {
          "label": "Signal",
          "value": "Shopify global object"
        },
        {
          "label": "Signal",
          "value": "x-shopid / powered-by Shopify header"
        }
      ],
      "fix": {
        "summary": "Fix order for Shopify:",
        "steps": [
          "Edit robots.txt.liquid in Online Store → Themes → Edit code → Templates (add the template if it does not exist).",
          "Most Online Store 2.0 themes print Product JSON-LD from the product template. Check that barcode (GTIN), vendor (brand) and shipping/return policies are set in Shopify admin.",
          "Enable Agentic Storefronts in Shopify admin. Shopify publishes and maintains the UCP profile for you."
        ]
      }
    }
  ],
  "agentView": {
    "url": "https://kestrelpine.example/products/alpine-merino-hoodie",
    "rawExcerpt": "<header class=\"header\">\n<a href=\"https://kestrelpine.example/\" class=\"header__heading-link\">\n<img src=\"https://kestrelpine.example/cdn/shop/files/kestrel-pine-logo.svg\" alt=\"Kestrel &amp; Pine\">\n</a>\n<nav class=\"header__inline-menu\" aria-label=\"Main\">\n<ul class=\"list-menu\">\n<li>\n<a href=\"https://kestrelpine.example/collections/jackets\">Jackets</a>\n</li>\n<li>\n<a href=\"https://kestrelpine.example/collections/midlayers\">Midlayers</a>\n</li>\n<li>\n<a href=\"https://kestrelpine.example/collections/packs\">Packs</a>\n</li>\n<li>\n<a href=\"https://kestrelpine.example/pages/repairs\">Repairs</a>\n</li>\n<li>\n<a href=\"https://kestrelpine.example/blogs/field-notes\">Field notes</a>\n</li>\n</ul>\n</nav>\n</header>\n<main id=\"MainContent\" class=\"content-for-layout\" role=\"main\">\n<section class=\"product\">\n<div class=\"product__media\">\n<img src=\"https://kestrelpine.example/cdn/shop/files/alpine-merino-hoodie-moss.jpg\" alt=\"Alpine Merino Hoodie in moss green, front view\">\n</div>\n<div class=\"product__info-container\">\n<p class=\"product__text caption\">Kestrel &amp; Pine</p>\n<h1>Alpine Merino Hoodie</h1>\n<div class=\"price\">\n<span class=\"price-item price-item--regular\">€129,00</span>\n<small>incl. VAT</small>\n</div>\n<p class=\"product__rating\">4.8 out of 5 from 312 reviews</p>\n<form method=\"post\" action=\"/cart/add\" id=\"product-form\" accept-charset=\"UTF-8\" class=\"form\" enctype=\"multipart/form-data\">\n<input type=\"hidden\" name=\"id\" value=\"4410\">\n<fieldset>\n<legend>Size</legend>\n<label>\n<input type=\"radio\" name=\"Size\" value=\"S\">S</label>\n<label>\n<input type=\"radio\" name=\"Size\" value=\"M\" checked>M</label>\n<label>\n<input type=\"radio\" name=\"Size\" value=\"L\">L</label>\n</fieldset>\n<button type=\"submit\" name=\"add\" class=\"product-form__submit button\">Add to cart</button>\n</form>\n<p class=\"stock\">In stock. Ships from Zagreb within 1 business day.</p>\n<div class=\"product__description rte\">\n<p>Our warmest midlayer, cut long in the back for climbing and cycling. 260 g/m² merino jersey regulates temperature from 5&deg;C mornings to 20&deg;C afternoons and stays fresh for days.</p>\n<ul>\n<li>100% ZQ-certified merino wool, 260 g/m²</li>\n<li>Scuba hood that fits under a helmet</li>\n<li>Flatlock seams, thumb loops, kangaroo pocket</li>\n<li>EAN 3856012345678</li>\n</ul>\n</div>\n<h2>Shipping and returns</h2>\n<p>Free delivery to Croatia, Slovenia, Austria and Germany in 1–4 business days. Free returns within 30 days, twice the 14 days EU law requires.</p>\n<h2>Care</h2>\n<p>Machine wash cold on the wool cycle. Dry flat. We repair holes, seams and cuffs for free, forever.</p>\n</div>\n</section>\n</main>\n<footer class=\"foote\n<!-- … 1 KB more -->",
    "markdown": "![Alpine Merino Hoodie in moss green, front view]\n\nKestrel & Pine\n\n# Alpine Merino Hoodie\n\n€129,00 incl. VAT\n\n4.8 out of 5 from 312 reviews\n\nIn stock. Ships from Zagreb within 1 business day.\n\nOur warmest midlayer, cut long in the back for climbing and cycling. 260 g/m² merino jersey regulates temperature from 5°C mornings to 20°C afternoons and stays fresh for days.\n\n- 100% ZQ-certified merino wool, 260 g/m²\n- Scuba hood that fits under a helmet\n- Flatlock seams, thumb loops, kangaroo pocket\n- EAN 3856012345678\n\n## Shipping and returns\n\nFree delivery to Croatia, Slovenia, Austria and Germany in 1–4 business days. Free returns within 30 days, twice the 14 days EU law requires.\n\n## Care\n\nMachine wash cold on the wool cycle. Dry flat. We repair holes, seams and cuffs for free, forever.",
    "tokens": 199,
    "htmlBytes": 6539,
    "facts": [
      {
        "label": "Product name",
        "value": "Alpine Merino Hoodie",
        "source": "both"
      },
      {
        "label": "Price",
        "value": "EUR 129.00",
        "source": "both"
      },
      {
        "label": "Availability",
        "value": "InStock",
        "source": "both"
      },
      {
        "label": "Brand",
        "value": "Kestrel & Pine",
        "source": "json-ld"
      },
      {
        "label": "GTIN / EAN",
        "value": "3856012345678",
        "source": "json-ld"
      },
      {
        "label": "Shipping",
        "value": "Declared in JSON-LD",
        "source": "both"
      },
      {
        "label": "Returns",
        "value": "Declared in JSON-LD",
        "source": "both"
      },
      {
        "label": "Rating",
        "value": "Declared in JSON-LD",
        "source": "both"
      }
    ]
  },
  "fetchLog": [
    {
      "url": "https://kestrelpine.example/",
      "purpose": "Homepage (as LegibleBot)",
      "status": 200,
      "ms": 202,
      "bytes": 5336
    },
    {
      "url": "https://kestrelpine.example/",
      "purpose": "Homepage (as a browser, for bot-wall comparison)",
      "status": 200,
      "ms": 202,
      "bytes": 5336
    },
    {
      "url": "https://kestrelpine.example/robots.txt",
      "purpose": "robots.txt",
      "status": 200,
      "ms": 84,
      "bytes": 714
    },
    {
      "url": "http://kestrelpine.example/",
      "purpose": "HTTP to HTTPS redirect probe",
      "status": 301,
      "ms": 50,
      "bytes": 0
    },
    {
      "url": "https://kestrelpine.example/llms.txt",
      "purpose": "llms.txt",
      "status": 200,
      "ms": 90,
      "bytes": 1020
    },
    {
      "url": "https://kestrelpine.example/llms-full.txt",
      "purpose": "llms-full.txt",
      "status": 404,
      "ms": 130,
      "bytes": 89
    },
    {
      "url": "https://kestrelpine.example/.well-known/ucp",
      "purpose": "UCP business profile",
      "status": 200,
      "ms": 108,
      "bytes": 2243
    },
    {
      "url": "https://kestrelpine.example/sitemap.xml",
      "purpose": "XML sitemap",
      "status": 200,
      "ms": 140,
      "bytes": 459
    },
    {
      "url": "https://kestrelpine.example/sitemap_products_1.xml?from=1&to=99",
      "purpose": "Product sitemap",
      "status": 200,
      "ms": 160,
      "bytes": 1371
    },
    {
      "url": "https://kestrelpine.example/products/alpine-merino-hoodie",
      "purpose": "Product page (as LegibleBot)",
      "status": 200,
      "ms": 710,
      "bytes": 6539
    }
  ],
  "protocols": {
    "ucp": "2026-08-25",
    "robotsAgents": "2026-10-07"
  }
}