{
  "schema": 1,
  "id": "demo-atlas-ceramics",
  "url": "https://atlasceramics.example/",
  "host": "atlasceramics.example",
  "productUrl": "https://atlasceramics.example/products/ember-stoneware-mug",
  "scannedAt": "2026-10-06T09:14:00.000Z",
  "durationMs": 1400,
  "demo": true,
  "siteName": "Atlas Ceramics Studio",
  "platform": {
    "platform": "custom",
    "confidence": "medium",
    "signals": [
      "Next.js application",
      "x-powered-by: Next.js"
    ]
  },
  "score": 57,
  "rawScore": 57,
  "cap": null,
  "grade": "D",
  "pillars": [
    {
      "pillar": "access",
      "score": 87,
      "counts": {
        "pass": 7,
        "warn": 1,
        "fail": 0,
        "info": 1
      }
    },
    {
      "pillar": "understanding",
      "score": 38,
      "counts": {
        "pass": 0,
        "warn": 5,
        "fail": 2,
        "info": 0
      }
    },
    {
      "pillar": "trust",
      "score": 61,
      "counts": {
        "pass": 1,
        "warn": 3,
        "fail": 0,
        "info": 0
      }
    },
    {
      "pillar": "transaction",
      "score": 34,
      "counts": {
        "pass": 1,
        "warn": 1,
        "fail": 2,
        "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://atlasceramics.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": "warn",
      "score": 0.5,
      "summary": "robots.txt blocks ChatGPT-User. Some of these may ignore the rule, but the intent turns shoppers' assistants away.",
      "evidence": [
        {
          "label": "OAI-SearchBot (OpenAI)",
          "value": "Allowed",
          "status": "pass"
        },
        {
          "label": "ChatGPT-User (OpenAI)",
          "value": "Blocked on / by \"Disallow: /\" (line 10)",
          "status": "fail"
        },
        {
          "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"
        }
      ],
      "fix": {
        "summary": "Allow search and user-triggered agents explicitly. Keep blocking training crawlers if you want to.",
        "steps": [
          "Serve robots.txt as text/plain from the site root and append the agent groups below."
        ],
        "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: /\nAllow: /\nDisallow: /api/\nDisallow: /cart\nDisallow: /checkout\nDisallow: /account\n\n# Training crawlers: your current choice is kept. Blocking them does\n# not remove you from AI search.\nUser-agent: GPTBot\nDisallow: /\n\nUser-agent: ClaudeBot\nUser-agent: Google-Extended\nUser-agent: Applebot-Extended\nUser-agent: Amazonbot\nUser-agent: meta-externalagent\nUser-agent: CCBot\nUser-agent: Bytespider\nAllow: /\nAllow: /\nDisallow: /api/\nDisallow: /cart\nDisallow: /checkout\nDisallow: /account\n\nSitemap: https://atlasceramics.example/sitemap.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": "1 training crawler blocked, 7 allowed.",
      "evidence": [
        {
          "label": "GPTBot (OpenAI)",
          "value": "Blocked"
        },
        {
          "label": "ClaudeBot (Anthropic)",
          "value": "Allowed"
        },
        {
          "label": "Google-Extended (Google)",
          "value": "Allowed"
        },
        {
          "label": "Applebot-Extended (Apple)",
          "value": "Allowed"
        },
        {
          "label": "Amazonbot (Amazon)",
          "value": "Allowed"
        },
        {
          "label": "meta-externalagent (Meta)",
          "value": "Allowed"
        },
        {
          "label": "CCBot (Common Crawl)",
          "value": "Allowed"
        },
        {
          "label": "Bytespider (ByteDance)",
          "value": "Allowed"
        }
      ]
    },
    {
      "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 3 product URLs.",
      "evidence": [
        {
          "label": "Location",
          "value": "https://atlasceramics.example/sitemap.xml"
        },
        {
          "label": "Found via",
          "value": "robots.txt"
        },
        {
          "label": "Type",
          "value": "URL set (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": "pass",
      "score": 1,
      "summary": "Slowest time to first byte: 420 ms.",
      "evidence": [
        {
          "label": "/",
          "value": "96 ms",
          "status": "pass"
        },
        {
          "label": "/products/ember-stoneware-mug",
          "value": "420 ms",
          "status": "pass"
        }
      ]
    },
    {
      "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": "119 KB of HTML for /products/ember-stoneware-mug.",
      "evidence": [
        {
          "label": "HTML size",
          "value": "119 KB"
        },
        {
          "label": "Inline script",
          "value": "118 KB in 4 tags"
        },
        {
          "label": "Visible words",
          "value": "0"
        }
      ]
    },
    {
      "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": "fail",
      "score": 0,
      "summary": "The product page is a JavaScript shell. Without running scripts an agent sees no product.",
      "evidence": [
        {
          "label": "Visible words (no JS)",
          "value": "0",
          "status": "fail"
        },
        {
          "label": "Product name in text",
          "value": "No",
          "status": "fail"
        },
        {
          "label": "Price in text",
          "value": "Not found",
          "status": "fail"
        },
        {
          "label": "Shell signal",
          "value": "Only 0 words of visible text in the raw HTML",
          "status": "fail"
        },
        {
          "label": "Shell signal",
          "value": "Empty Next.js root (#__next)",
          "status": "fail"
        },
        {
          "label": "Shell signal",
          "value": "\"Enable JavaScript\" notice in the HTML",
          "status": "fail"
        }
      ],
      "fix": {
        "summary": "Render product content on the server.",
        "steps": [
          "Server-render (SSR or static generation) the product name, price, availability and description. Hydrate interactivity afterwards."
        ]
      }
    },
    {
      "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.7307692307692307,
      "summary": "Product schema is 73% complete. Missing: gtin / mpn, shippingDetails, hasMerchantReturnPolicy and aggregateRating.",
      "evidence": [
        {
          "label": "name",
          "value": "Ember Stoneware Mug",
          "status": "pass"
        },
        {
          "label": "image",
          "value": "https://atlasceramics.example/images/ember-mug.jpg",
          "status": "pass"
        },
        {
          "label": "description",
          "value": "A 350 ml hand-thrown stoneware mug in a speckled ember glaze.",
          "status": "pass"
        },
        {
          "label": "offers.price",
          "value": "34",
          "status": "pass"
        },
        {
          "label": "offers.priceCurrency",
          "value": "EUR",
          "status": "pass"
        },
        {
          "label": "offers.availability",
          "value": "https://schema.org/InStock",
          "status": "pass"
        },
        {
          "label": "sku",
          "value": "ATL-MUG-EMB",
          "status": "pass"
        },
        {
          "label": "gtin / mpn",
          "value": "missing",
          "status": "warn"
        },
        {
          "label": "brand",
          "value": "Atlas Ceramics Studio",
          "status": "pass"
        },
        {
          "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": [
          "Print one Product JSON-LD block per product page, server-side, generated from the same data that renders the visible price."
        ],
        "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\": \"Ember Stoneware Mug\",\n  \"description\": \"A 350 ml hand-thrown stoneware mug in a speckled ember glaze.\",\n  \"image\": [\n    \"https://atlasceramics.example/images/ember-mug.jpg\"\n  ],\n  \"sku\": \"ATL-MUG-EMB\",\n  \"gtin\": \"REPLACE_BARCODE_OR_DELETE_THIS_LINE\",\n  \"brand\": {\n    \"@type\": \"Brand\",\n    \"name\": \"Atlas Ceramics Studio\"\n  },\n  \"offers\": {\n    \"@type\": \"Offer\",\n    \"url\": \"https://atlasceramics.example/products/ember-stoneware-mug\",\n    \"price\": \"34.00\",\n    \"priceCurrency\": \"EUR\",\n    \"availability\": \"https://schema.org/InStock\",\n    \"itemCondition\": \"https://schema.org/NewCondition\",\n    \"seller\": {\n      \"@type\": \"Organization\",\n      \"name\": \"Atlas Ceramics Studio\"\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": "warn",
      "score": 0.5,
      "summary": "Organization schema found; WebSite missing.",
      "evidence": [
        {
          "label": "Organization",
          "value": "Atlas Ceramics Studio",
          "status": "pass"
        },
        {
          "label": "WebSite",
          "value": "missing",
          "status": "warn"
        },
        {
          "label": "logo",
          "value": "present",
          "status": "pass"
        },
        {
          "label": "sameAs",
          "value": "present",
          "status": "pass"
        }
      ],
      "fix": {
        "summary": "Add an Organization (or OnlineStore) and WebSite graph to the homepage.",
        "snippet": {
          "language": "html",
          "filename": "Homepage <head>",
          "code": "<!-- Organization and WebSite JSON-LD generated by Legible.\n     Replace every REPLACE_… value with your real details before publishing. -->\n<script type=\"application/ld+json\">\n{\n  \"@context\": \"https://schema.org\",\n  \"@graph\": [\n    {\n      \"@type\": \"OnlineStore\",\n      \"@id\": \"https://atlasceramics.example/#org\",\n      \"name\": \"Atlas Ceramics Studio\",\n      \"url\": \"https://atlasceramics.example/\",\n      \"logo\": \"https://atlasceramics.example/logo.png\",\n      \"email\": \"studio@atlasceramics.example\",\n      \"telephone\": \"REPLACE_PHONE\",\n      \"address\": {\n        \"@type\": \"PostalAddress\",\n        \"streetAddress\": \"REPLACE_STREET\",\n        \"postalCode\": \"REPLACE_POSTCODE\",\n        \"addressLocality\": \"REPLACE_CITY\",\n        \"addressCountry\": \"REPLACE_COUNTRY_CODE\"\n      },\n      \"legalName\": \"REPLACE_LEGAL_NAME\",\n      \"vatID\": \"REPLACE_VAT_ID\",\n      \"sameAs\": [\n        \"https://www.instagram.com/atlasceramics.example\"\n      ]\n    },\n    {\n      \"@type\": \"WebSite\",\n      \"@id\": \"https://atlasceramics.example/#website\",\n      \"name\": \"Atlas Ceramics Studio\",\n      \"url\": \"https://atlasceramics.example/\",\n      \"publisher\": {\n        \"@id\": \"https://atlasceramics.example/#org\"\n      }\n    }\n  ]\n}\n</script>"
        }
      }
    },
    {
      "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": "warn",
      "score": 0.5,
      "summary": "Missing og:description and og:url.",
      "evidence": [
        {
          "label": "og:title",
          "value": "Ember Stoneware Mug",
          "status": "pass"
        },
        {
          "label": "og:description",
          "value": "missing",
          "status": "warn"
        },
        {
          "label": "og:image",
          "value": "https://atlasceramics.example/images/ember-mug.jpg",
          "status": "pass"
        },
        {
          "label": "og:url",
          "value": "missing",
          "status": "warn"
        },
        {
          "label": "og:type",
          "value": "product",
          "status": "pass"
        }
      ],
      "fix": {
        "summary": "Add og:description and og:url 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": "warn",
      "score": 0.5,
      "summary": "<link rel=\"canonical\"> is missing.",
      "evidence": [
        {
          "label": "canonical",
          "value": "missing",
          "status": "warn"
        },
        {
          "label": "html lang",
          "value": "en",
          "status": "pass"
        }
      ],
      "fix": {
        "summary": "Add <link rel=\"canonical\">."
      }
    },
    {
      "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": "fail",
      "score": 0,
      "summary": "The product page has no H1.",
      "evidence": [
        {
          "label": "H1",
          "value": "none",
          "status": "warn"
        },
        {
          "label": "H2",
          "value": "0"
        }
      ],
      "fix": {
        "summary": "Mark the product name up as the page's only <h1>."
      }
    },
    {
      "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. The server answers /llms.txt with an HTML page and HTTP 200, so agents get a page instead of a 404.",
      "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": [
          "Serve /llms.txt as text/plain or text/markdown from the site root."
        ],
        "snippet": {
          "language": "markdown",
          "filename": "/llms.txt",
          "code": "# Atlas Ceramics Studio\n\n> Handmade stoneware from a two-person studio in Split. Mugs, plates, bowls and vases, glazed in small batches.\n\n## Products\n\n- [Ember Stoneware Mug](https://atlasceramics.example/products/ember-stoneware-mug)\n- [Tide Dinner Plate](https://atlasceramics.example/products/tide-dinner-plate)\n- [Cove Bud Vase](https://atlasceramics.example/products/cove-bud-vase)\n\n## Categories\n\n- [Tableware](https://atlasceramics.example/collections/tableware)\n- [Vases](https://atlasceramics.example/collections/vases)\n\n## Policies\n\n- [Shipping](https://atlasceramics.example/help/shipping)\n- [Returns](https://atlasceramics.example/help/returns)\n- [Privacy](https://atlasceramics.example/privacy)\n- [Contact](https://atlasceramics.example/contact)\n\n## Optional\n\n- [Journal](https://atlasceramics.example/journal)\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": "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 (308)",
          "status": "pass"
        },
        {
          "label": "Strict-Transport-Security",
          "value": "max-age=63072000; includeSubDomains; preload",
          "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": "warn",
      "score": 0.5,
      "summary": "Terms not linked.",
      "evidence": [
        {
          "label": "Shipping",
          "value": "https://atlasceramics.example/help/shipping",
          "status": "pass"
        },
        {
          "label": "Returns",
          "value": "https://atlasceramics.example/help/returns",
          "status": "pass"
        },
        {
          "label": "Privacy",
          "value": "https://atlasceramics.example/privacy",
          "status": "pass"
        },
        {
          "label": "Terms",
          "value": "no link found",
          "status": "warn"
        },
        {
          "label": "Contact",
          "value": "https://atlasceramics.example/contact",
          "status": "pass"
        }
      ],
      "fix": {
        "summary": "Link terms from the site footer.",
        "steps": [
          "Link every policy page from a site-wide footer with plain anchor links agents can follow."
        ]
      }
    },
    {
      "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 and legal name or VAT ID are missing.",
      "evidence": [
        {
          "label": "address",
          "value": "missing",
          "status": "fail"
        },
        {
          "label": "email / telephone / contactPoint",
          "value": "present",
          "status": "pass"
        },
        {
          "label": "legalName / vatID",
          "value": "missing",
          "status": "warn"
        }
      ],
      "fix": {
        "summary": "Add address 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": "warn",
      "score": 0.5,
      "summary": "JSON-LD says EUR 34.00, but no price is visible in the raw HTML.",
      "evidence": [
        {
          "label": "JSON-LD price",
          "value": "EUR 34.00"
        },
        {
          "label": "Current prices on page",
          "value": "none found"
        },
        {
          "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": "fail",
      "score": 0.25,
      "summary": "UCP profile found with 2 spec errors: Required \"transport\": one of rest, mcp, a2a, embedded.",
      "evidence": [
        {
          "label": "ucp.version",
          "value": "2026-01-11",
          "status": "warn"
        },
        {
          "label": "Services",
          "value": "dev.ucp.shopping"
        },
        {
          "label": "Transports",
          "value": "none"
        },
        {
          "label": "Capabilities",
          "value": "none",
          "status": "warn"
        },
        {
          "label": "Payment handlers",
          "value": "none"
        },
        {
          "label": "Signing keys",
          "value": "none"
        },
        {
          "label": "$.ucp.version",
          "value": "Version 2026-01-11 is valid but not the latest (2026-08-25). Agents negotiate down, so this still works.",
          "status": "warn"
        },
        {
          "label": "$.ucp.services.dev.ucp.shopping",
          "value": "Service bindings should be an array (one entry per transport).",
          "status": "warn"
        },
        {
          "label": "$.ucp.services.dev.ucp.shopping[0].transport",
          "value": "Required \"transport\": one of rest, mcp, a2a, embedded.",
          "status": "fail"
        },
        {
          "label": "$.ucp.capabilities",
          "value": "Capabilities must be an object keyed by capability name. An array is not the published form.",
          "status": "fail"
        },
        {
          "label": "$.keys",
          "value": "No signing keys published. Recommended so agents can verify signed responses.",
          "status": "warn"
        }
      ],
      "fix": {
        "summary": "Publish a UCP profile backed by a working checkout implementation.",
        "steps": [
          "Implement the UCP REST or MCP binding for checkout, then publish the profile at /.well-known/ucp."
        ],
        "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://atlasceramics.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": "warn",
      "score": 0.5,
      "summary": "One catalogue signal: Product URLs in the sitemap (3).",
      "evidence": [
        {
          "label": "Signal",
          "value": "Product URLs in the sitemap (3)",
          "status": "pass"
        }
      ],
      "fix": {
        "summary": "Expose a product feed and submit it to agent channels.",
        "steps": [
          "Expose a product feed (Google Merchant Center format works for most agent channels) and a product sitemap."
        ]
      }
    },
    {
      "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.",
          "Expose a product feed (Google Merchant Center format works for most agent channels) and a product sitemap."
        ]
      }
    },
    {
      "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": "fail",
      "score": 0,
      "summary": "No add-to-cart control in the server HTML.",
      "evidence": [
        {
          "label": "Cart form in HTML",
          "value": "no",
          "status": "warn"
        },
        {
          "label": "Add-to-cart link",
          "value": "no"
        },
        {
          "label": "Add-to-cart button",
          "value": "no",
          "status": "warn"
        }
      ],
      "fix": {
        "summary": "Render a real form that posts to your cart endpoint and works before scripts load; let JavaScript enhance it.",
        "snippet": {
          "language": "html",
          "filename": "Product template",
          "code": "<form method=\"post\" action=\"/cart/add\">\n  <input type=\"hidden\" name=\"sku\" value=\"SKU\">\n  <input type=\"number\" name=\"quantity\" value=\"1\" min=\"1\">\n  <button type=\"submit\">Add to cart</button>\n</form>"
        },
        "steps": [
          "Server-render (SSR or static generation) the product name, price, availability and description. Hydrate interactivity afterwards."
        ]
      }
    },
    {
      "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 Custom or headless (medium confidence).",
      "evidence": [
        {
          "label": "Signal",
          "value": "Next.js application"
        },
        {
          "label": "Signal",
          "value": "x-powered-by: Next.js"
        }
      ],
      "fix": {
        "summary": "Fix order for Custom or headless:",
        "steps": [
          "Serve robots.txt as text/plain from the site root and append the agent groups below.",
          "Print one Product JSON-LD block per product page, server-side, generated from the same data that renders the visible price.",
          "Implement the UCP REST or MCP binding for checkout, then publish the profile at /.well-known/ucp."
        ]
      }
    }
  ],
  "agentView": {
    "url": "https://atlasceramics.example/products/ember-stoneware-mug",
    "rawExcerpt": "<div id=\"__next\">\n<div class=\"app-loading\" aria-busy=\"true\">\n</div>\n</div>\n<noscript>You need to enable JavaScript to run this app.</noscript>\n<script>/* 117 KB */</script>\n<script type=\"application/json\">/* 503 B */</script>",
    "markdown": "(The raw HTML contains no readable content.)",
    "tokens": 0,
    "htmlBytes": 122129,
    "facts": [
      {
        "label": "Product name",
        "value": "Ember Stoneware Mug",
        "source": "json-ld"
      },
      {
        "label": "Price",
        "value": "EUR 34.00",
        "source": "json-ld"
      },
      {
        "label": "Availability",
        "value": "InStock",
        "source": "json-ld"
      },
      {
        "label": "Brand",
        "value": "Atlas Ceramics Studio",
        "source": "json-ld"
      },
      {
        "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://atlasceramics.example/",
      "purpose": "Homepage (as LegibleBot)",
      "status": 200,
      "ms": 116,
      "bytes": 2819
    },
    {
      "url": "https://atlasceramics.example/",
      "purpose": "Homepage (as a browser, for bot-wall comparison)",
      "status": 200,
      "ms": 116,
      "bytes": 2819
    },
    {
      "url": "https://atlasceramics.example/robots.txt",
      "purpose": "robots.txt",
      "status": 200,
      "ms": 60,
      "bytes": 208
    },
    {
      "url": "http://atlasceramics.example/",
      "purpose": "HTTP to HTTPS redirect probe",
      "status": 308,
      "ms": 42,
      "bytes": 0
    },
    {
      "url": "https://atlasceramics.example/llms.txt",
      "purpose": "llms.txt",
      "status": 200,
      "ms": 80,
      "bytes": 679
    },
    {
      "url": "https://atlasceramics.example/llms-full.txt",
      "purpose": "llms-full.txt",
      "status": 200,
      "ms": 80,
      "bytes": 679
    },
    {
      "url": "https://atlasceramics.example/.well-known/ucp",
      "purpose": "UCP business profile",
      "status": 200,
      "ms": 95,
      "bytes": 322
    },
    {
      "url": "https://atlasceramics.example/sitemap.xml",
      "purpose": "XML sitemap",
      "status": 200,
      "ms": 90,
      "bytes": 532
    },
    {
      "url": "https://atlasceramics.example/products/ember-stoneware-mug",
      "purpose": "Product page (as LegibleBot)",
      "status": 200,
      "ms": 440,
      "bytes": 122129
    }
  ],
  "protocols": {
    "ucp": "2026-08-25",
    "robotsAgents": "2026-10-07"
  }
}