{
 "tool": "aicrawlercheck",
 "raw_files": [
  "raw/acc_main_lab2.json",
  "raw/acc_geo_lab2.json",
  "raw/acc_diag_lab2.json",
  "raw/acc_main_lab2-clean.json",
  "raw/acc_geo_lab2-clean.json",
  "raw/acc_diag_lab2-clean.json"
 ],
 "reach": {
  "fetched_paths": [
   "/",
   "/unavailable (as ClaudeBot, following the 302)",
   "/robots.txt",
   "/llms.txt",
   "/llms-full.txt (404)",
   "/sitemap.xml",
   "/sitemap_index.xml (404)",
   "/sitemap/sitemap.xml (404)",
   "/wp-sitemap.xml (404)",
   "/.well-known/http-message-signatures-directory (404)"
  ],
  "agents": [
   "Chrome 124/128 desktop",
   "Googlebot smartphone",
   "Googlebot/2.1",
   "bingbot/2.0",
   "GPTBot/1.1",
   "OAI-SearchBot/1.0",
   "ChatGPT-User/1.0",
   "ClaudeBot/1.0",
   "Claude-SearchBot/1.0",
   "Claude-User/1.0",
   "PerplexityBot/1.0",
   "Perplexity-User/1.0",
   "meta-externalagent/1.1",
   "Bytespider",
   "Amazonbot/0.1",
   "DuckAssistBot/1.2",
   "CCBot/2.0",
   "MistralAI-User/1.0",
   "cohere-ai",
   "YouBot/1.0",
   "AICrawlerCheck/3.0,4.0,6.1, -GEOAudit/2.0, -Diagnostic/1.0"
  ],
  "not_fetched": "No Applebot request (Applebot-Extended treated as a robots-only token); no sub-pages; no sitemap-pages.xml; no security.txt."
 },
 "faults": {
  "R1": {
   "v": "caught",
   "quote": "Blocked by robots.txt: the \"User-agent: ClaudeBot\" group, line 11: Disallow: /",
   "where": "acc_diag_lab2.json issues[0].title (also acc_geo_lab2.json data.crawlers[ClaudeBot].rule \"Disallow: / (line 11)\")",
   "note": "Contradicted by the main endpoint: acc_main_lab2.json bots.ClaudeBot.robotsTxt = ALLOWED, \"Disallow: (empty)\". Graded on the endpoints that apply the reference-parser reading.",
   "loc": "robots"
  },
  "R2": {
   "v": "partial",
   "quote": "Full content access; 2 path rules (/assets/, /quote)",
   "where": "acc_main_lab2.json bots.GPTBot.robotsTxt.rule (same on every wildcard bot)",
   "note": "The /assets/ Disallow is shown, but framed as \"Full content access\"; nothing says the render resources are blocked.",
   "loc": "robots"
  },
  "R3": {
   "v": "caught",
   "quote": "Googlebot-Image, Storebot-Google are blocked. This directly impacts your SEO rankings.",
   "where": "acc_main_lab2.json recommendations[0].description; crawlability.robots[1].rule \"Disallow: / (line 11, its own Googlebot-Image group)\"",
   "loc": "robots"
  },
  "R4": {
   "v": "caught",
   "quote": "Googlebot-Image, Storebot-Google are blocked. This directly impacts your SEO rankings.",
   "where": "acc_main_lab2.json recommendations[0].description; bots.Storebot-Google.robotsTxt \"Disallow: /\"",
   "loc": "robots"
  },
  "R5": {
   "v": "missed",
   "quote": "",
   "where": "",
   "loc": "robots"
  },
  "R6": {
   "v": "partial",
   "quote": "Sitemap index with 2 child sitemaps at https://lab2.crawlcheck.io/sitemap.xml. Not declared in robots.txt.",
   "where": "acc_geo_lab2.json data.criteria[sitemap].evidence (same in acc_main geoAudit)",
   "note": "The relative Sitemap line is reported as absent rather than invalid; the owner is pointed at the right line but told the wrong thing about it.",
   "loc": "robots"
  },
  "R7": {
   "v": "missed",
   "quote": "",
   "where": "",
   "loc": "robots"
  },
  "S1": {
   "v": "caught",
   "quote": "Firewall treats these crawlers differently from a browser: HTTP 403 when requested as PerplexityBot, while a normal browser gets HTTP 200",
   "where": "acc_diag_lab2.json issues[2].title",
   "note": "acc_main_lab2.json still lists bots.PerplexityBot.effectiveStatus = \"ALLOWED\" (robots-only field).",
   "loc": "home:PerplexityBot"
  },
  "S2": {
   "v": "missed",
   "quote": "",
   "where": "",
   "note": "Set by the independent verification pass (grades/_verification.json).",
   "loc": "home:Applebot"
  },
  "S3": {
   "v": "missed",
   "quote": "",
   "where": "",
   "note": "OAI-SearchBot was fetched (log 1839124, 1839850) and the diag shows \"877 characters of text\" vs 1,138 for other agents (acc_diag_lab2.json results[OAI-SearchBot].gates.js.detail) but it is not compared or flagged; verdict \"Reachable ... Nothing to fix\".",
   "loc": "home:OAI-SearchBot"
  },
  "S4": {
   "v": "partial",
   "quote": "1 redirect, ending at https://lab2.crawlcheck.io/unavailable",
   "where": "acc_diag_lab2.json results[ClaudeBot].gates.redirects.detail (ok:true)",
   "note": "The 302 to /unavailable is visible but the redirect gate is marked ok and the status gate reports \"HTTP 200\"; the verdict blames robots.txt instead. js gate does note \"Only 37 characters of text\".",
   "loc": "home:ClaudeBot"
  },
  "S5": {
   "v": "caught",
   "quote": "HTTP 429 for GPTBot, while a browser gets 200. Tested with the crawler user agent from our server, not the crawler IP range.",
   "where": "acc_geo_lab2.json data.criteria[firewall].evidence; acc_diag_lab2.json issues[1].title",
   "note": "acc_main_lab2.json bots.GPTBot.effectiveStatus = \"ALLOWED\" and score 89 \"Good\" contradict this.",
   "loc": "home:GPTBot"
  },
  "S6": {
   "v": "missed",
   "quote": "",
   "where": "",
   "note": "Googlebot was fetched; diag shows 1,229 characters vs 1,138 for the browser-equivalent agents, not compared or flagged; verdict \"Reachable\".",
   "loc": "home:Googlebot"
  },
  "S7": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "note": "/pricing never fetched.",
   "loc": "sub:/pricing:Bingbot"
  },
  "I1": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/services/gutter-guards"
  },
  "I2": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/pricing"
  },
  "I3": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/areas/riverbend"
  },
  "I4": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/services/downspout-repair"
  },
  "I5": {
   "v": "caught",
   "quote": "nosnippet or max-snippet:0 is set.",
   "where": "acc_geo_lab2.json data.criteria[nosnippet].evidence; acc_main_lab2.json crawlability.gates[index].detail \"<meta name=\\\"robots\\\"> says \\\"nosnippet\\\"\"",
   "loc": "home"
  },
  "I6": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/faq"
  },
  "I7": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/about"
  },
  "J1": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/pricing"
  },
  "J2": {
   "v": "missed",
   "quote": "",
   "where": "",
   "loc": "home"
  },
  "J3": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/reviews"
  },
  "J4": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/faq"
  },
  "J5": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/gallery"
  },
  "J6": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/careers"
  },
  "D1": {
   "v": "caught",
   "quote": "1 JSON-LD block, none of them valid JSON.",
   "where": "acc_geo_lab2.json data.criteria[schema_present].evidence",
   "note": "The main endpoint words it worse: recommendations[1] \"No Schema.org markup detected on your homepage.\"",
   "loc": "home"
  },
  "D2": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/contact"
  },
  "D3": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/contact"
  },
  "D4": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/reviews"
  },
  "D5": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/about"
  },
  "D6": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/about"
  },
  "D7": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/blog/*"
  },
  "M1": {
   "v": "missed",
   "quote": "",
   "where": "",
   "loc": "llms"
  },
  "M2": {
   "v": "missed",
   "quote": "",
   "where": "",
   "loc": "llms"
  },
  "M3": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "security"
  },
  "M4": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "security"
  },
  "M5": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "security"
  },
  "X1": {
   "v": "missed",
   "quote": "",
   "where": "",
   "loc": "smidx"
  },
  "X2": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "smpages"
  },
  "X3": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "smpages"
  },
  "X4": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "smpages"
  },
  "X5": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "smpages"
  },
  "X6": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "smpages"
  },
  "L1": {
   "v": "missed",
   "quote": "",
   "where": "",
   "loc": "home"
  },
  "L2": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/old-gutter-page"
  },
  "L3": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/blog/do-gutter-guards-work,/promo-a"
  },
  "L4": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/specials"
  },
  "L5": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "smpages"
  },
  "L6": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/faq/"
  },
  "L7": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/about"
  },
  "P1": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/careers"
  },
  "P2": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/areas/millbrook,/areas/cedar-park"
  },
  "P3": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/services/fascia-repair"
  },
  "P4": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/services/ice-dam-prevention"
  },
  "P5": {
   "v": "caught",
   "quote": "0 of 3 images have alt.",
   "where": "acc_geo_lab2.json data.criteria[image_alt].evidence",
   "loc": "home"
  },
  "P6": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/privacy"
  },
  "P7": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/terms"
  },
  "T1": {
   "v": "missed",
   "quote": "",
   "where": "",
   "loc": "home"
  },
  "T2": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/about"
  },
  "T3": {
   "v": "unreached",
   "quote": "",
   "where": "",
   "loc": "sub:/blog/do-gutter-guards-work"
  },
  "T4": {
   "v": "missed",
   "quote": "",
   "where": "",
   "loc": "home"
  }
 },
 "score": {
  "caught": 8,
  "partial": 3,
  "points": 9.5,
  "wrong": 0,
  "reached": 23,
  "points_of_reached": 0.413,
  "pct_of_63": 15.1
 },
 "clean": {
  "false_alarms": [],
  "advisories": [
   {
    "claim": "llms-full.txt missing",
    "quote": "Add llms-full.txt (optional)",
    "where": "acc_main_lab2-clean.json recommendations[0].title"
   },
   {
    "claim": "no named training-bot groups",
    "quote": "No training crawler is named; all follow the wildcard group.",
    "where": "acc_geo_lab2-clean.json data.criteria[training_policy]"
   },
   {
    "claim": "thin content",
    "quote": "144 words of main content.",
    "where": "acc_geo_lab2-clean.json data.criteria[content_depth] (fail)"
   },
   {
    "claim": "no question headings",
    "quote": "No headings phrased as questions.",
    "where": "criteria[question_headings]"
   },
   {
    "claim": "few H2s / lists",
    "quote": "Only 1 H2.",
    "where": "criteria[subheadings]; criteria[lists_tables] \"1 list, 0 tables.\""
   },
   {
    "claim": "no content-type schema",
    "quote": "Only site-level types (WebSite, WebPage, BreadcrumbList) or none.",
    "where": "criteria[schema_content]",
    "note": "Wording is literally inexact (the page has LocalBusiness, which is neither), but no Article/Product/FAQ/Service node exists, so the substance is true."
   },
   {
    "claim": "no BreadcrumbList",
    "quote": "No BreadcrumbList.",
    "where": "criteria[breadcrumbs]"
   },
   {
    "claim": "no Open Graph",
    "quote": "No Open Graph tags.",
    "where": "criteria[open_graph]"
   },
   {
    "claim": "no outbound links",
    "quote": "No links to external sources.",
    "where": "criteria[outbound_sources]"
   },
   {
    "claim": "no Web Bot Auth directory",
    "quote": "\"webBotAuthDirectory\": false",
    "where": "acc_main_lab2-clean.json webBotAuthDirectory"
   }
  ]
 },
 "other_false_claims_lab2": [],
 "evidence_quality": {
  "score": 3,
  "why": "Names the agent, the observed status (403/429), the robots line number and group, character counts per agent, and states its own method (\"Tested with the crawler user agent from our server, not the crawler IP range\")."
 },
 "strengths_not_scored": [
  "Robots verdicts for 265 user-agent tokens across 8 categories (acc_main_lab2.json totalBots 265).",
  "Live fetch of the homepage as 20 crawler user agents with six gates each (robots, directive, status, redirects, interstitial, JS) (acc_diag_lab2.json results).",
  "Honest caveat on fake-bot protection: \"Our request does not come from Perplexity AI's network, so we cannot tell which.\" (diag results[PerplexityBot].evidence).",
  "Robots group count matches Google's parser (\"returned 200 with 4 groups\", acc_diag_lab2.json robots.note).",
  "Googlebot crawlability gate set with an explicit caveat to confirm in Search Console (acc_main_lab2.json crawlability.note).",
  "Lists agentic browsers that cannot be detected at the HTTP layer (undetectableAgents).",
  "Clean twin: zero false alarms."
 ],
 "notes": "Graded as one tool across main (/api/check), diag (/api/diagnose) and GEO (/api/geo-audit/analyze). The three endpoints disagree with each other on lab2: main says ClaudeBot ALLOWED (\"Disallow: (empty)\"), GPTBot/PerplexityBot effectiveStatus ALLOWED, tier1BlockedCount 0, score 89 \"Good\"; diag and GEO say ClaudeBot blocked at line 11, GPTBot 429, PerplexityBot 403, and the GEO score is capped to 40/D by a firewall gate. A user who runs only the main check sees the wrong picture on R1, S1, S5; these were not graded wrong because another endpoint of the same free tool states the truth. Main also says \"No Schema.org markup detected on your homepage\" (recommendations[1]) where the markup exists but does not parse (D1, graded on the GEO wording). Homepage-only content checks: no sub-page, sitemap child or security.txt was fetched."
}