How the grade is made.
Every scan runs 187 checks against the real site: the real robots.txt, the real headers, the real TLS handshake, the real DNS records, up to 150 real pages. 164 checks are graded. 23 are informational only, observed and reported but never scored, because the evidence does not support grading them. This page is the full method: where checks come from, how they become one number, what every check weighs, and what that number honestly cannot tell you. The complete check table is at the bottom, generated from the engine's own registry.
A check exists only if a published source backs it.
The 116 scored on-page checks are grounded in official search engine documentation, primarily Google's published Search documentation. If Google documents it as a requirement or a stated signal, it can become a check. If it is folklore, it cannot. That is why AuditLamp has no title character-count rule: Google documents no such limit, so we refuse to grade one.
The 48 Vibe Audit checks each map to a named public standard: an OWASP project, an IETF RFC, a CWE entry, a WCAG 2.2 Success Criterion, or a named privacy law. The check-by-check mapping ships in the product; every finding cites its standard next to the verdict.
When guidance changes, checks change, on a stated cadence. An automated watch reads Google's published Search documentation changelog every day, and the key Search documentation pages are baselined for content-level diffs so a reworded requirement is caught even without a changelog entry. When a revision affects a check, the check updates and the finding prints its citation date, so a verdict never quietly rests on stale guidance. One example on the record: Google's July 10, 2026 guide revision was picked up and the affected citations were live within a day.
187 run. 164 graded. One blended number.
The on-page score comes from the 116 scored SEO, AEO and GEO checks with proportional credit: a check that passes on 9 of your 10 pages earns 90% of its weight, not zero. One bad page dents the score; it does not erase the 9 good ones.
The overall grade is 70% on-page score, 30% Vibe Audit. The Vibe portion is the mean of three pillars graded independently on an A+ to F band, the same style of band security scanners like SSL Labs use: security (23 checks: TLS, headers, exposed files, cookies, email authentication), accessibility (18 checks against WCAG 2.2 automatable criteria), and privacy (7 checks: trackers, consent, policy substance).
Severity is graded, not binary. Findings are split into fails, warns and threshold cases so a missing nice-to-have reads as a warn, never a catastrophe. One rule is deliberately blunt: a genuine site-breaking failure, like crawlers blocked from the entire site, caps the headline score at 79, names the exact failure on the report, and prints the score the site rises to once it is fixed. A high score with a broken front door would be a lie; the cap is how we refuse to tell it.
Edge cases are graded conservatively. A page with nothing for a given check to measure is excluded from that check's denominator: it is neither a pass nor a fail, so absence of evidence never inflates a score. A check that finds nothing to measure anywhere on the site reports exactly that ("observed across N pages, never scored") instead of rendering a green pass for measuring nothing. Failing pages reduce the passing fraction; a site we cannot reach at all voids the scan (and returns the free-scan slot) rather than being graded on pages we never read.
The 23 informational checks are observed across the crawl and reported with their evidence, but excluded from every score. When a check has nothing to measure on a site, it says so; it never renders as a green pass for measuring nothing.
Fetched, not estimated.
AuditLamp reads the live site the way crawlers do. A scan fetches the real pages (desktop and mobile), the real robots.txt and sitemap, llms.txt if present, performs a real TLS handshake, resolves SPF and DMARC over DNS, and probes well-known paths that should never be public. AI-crawler access is tested by named agent: Googlebot, Bingbot, GPTBot, ClaudeBot, PerplexityBot, Google-Extended.
Link-graph authority comes from our own index of the public Common Crawl domain graph: 121 million domains, 3.9 billion domain-to-domain links, rebuilt as Common Crawl publishes new data on its roughly monthly cycle. The score is the domain's harmonic-centrality position converted to 0 to 100 with a disclosed formula, authority = 100 * (1 - ln(harmonic_pos) / ln(N)), where N is the number of ranked domains. Referring-domain counts come from the same graph, deduplicated so one domain linking many times counts once. A domain absent from the graph is reported as "not in the index we read", never given an invented number.
What needs a rendered browser, we do not fake. Colour contrast, keyboard operability and runtime tracker capture require a real rendered page, so they are out of scope for the passive scan and documented as such, not silently graded.
The score is a hypothesis. Your rankings are the truth.
An audit score measures whether your site meets the documented requirements engines state. It is not a ranking prediction, and any tool that sells its score as one is overclaiming. The honest loop: fix what the scan names, then verify against reality. That is why the product connects to your own Google Search Console data, real queries, clicks and positions, so the grade gets checked against the only numbers that matter.
We run the method on ourselves. auditlamp.com is scanned by the same public engine, and the homepage pins the resulting report with a link anyone can open. The pinned report is immutable: a later scan cannot silently repaint the published number. When our own scan finds a fail, it stays on the report until we fix it for real.
What a clean grade does not mean.
Security: a clean pillar means nothing was exposed at the surface of a passive scan. It is not a penetration test and we never call it one.
Accessibility: automated tooling catches roughly 30 to 40% of WCAG. A clean pillar means no automatically detectable barriers were found, never "WCAG compliant" or "ADA compliant".
Privacy: observable signals only. Not legal advice, not a compliance certification.
These caveats print on the report itself, attached to every pillar grade. A tool that grades honestly has to state what its grades cannot see.
Full catalog of named checks: what we check. The plain-language story: how it works.
Every check, its job, and its weight.
This table is generated directly from the engine's check registry (registry version 0.2.0, regenerated 2026-07-17), so it cannot drift from what actually runs. Weights are relative within the on-page score; a weight-10 check moves the score ten times more than a weight-1 check. Vibe Audit weights work the same way inside their own pillar grade. The 23 informational checks carry no weight anywhere: they are observed and reported, never scored.
The 116 scored on-page checks
Gate: can machines reach you at all (8 checks)
| check id | what it verifies | weight |
|---|---|---|
gate.crawlable | Search crawler access | 10 |
gate.ai_bot_access | AI crawler access | 9 |
gate.bot_reachability | Firewall and CDN bot access | 6 |
gate.indexable | Indexing permission | 10 |
gate.renders_no_js | Content without JavaScript | 8 |
gate.sitemap | Sitemap | 5 |
gate.sitemap_quality | Sitemap quality | 4 |
gate.robots_quality | robots.txt quality | 3 |
Core: do you answer what people search (29 checks)
| check id | what it verifies | weight |
|---|---|---|
core.title | Page title | 8 |
core.meta_description | Meta description | 5 |
core.h1 | Main heading (H1) | 6 |
core.structured_data | Structured data (JSON-LD) | 7 |
core.schema_complete | Required schema fields | 5 |
core.answer_block | Answer near the top | 7 |
core.content_depth | Content depth | 7 |
core.mobile_parity | Mobile and desktop parity | 5 |
core.entity_consistency | Business identity markup | 4 |
corpus.unique_titles | Unique page titles | 7 |
corpus.duplicate_content | Duplicate content across pages | 5 |
core.topic_target | Topic targeting | 6 |
core.geo_target | Service + place targeting | 6 |
core.nap_consistency | Business identity (NAP) consistency | 6 |
core.local_schema | Local business structured data | 5 |
corpus.site_structure | Site structure (pages that can rank) | 6 |
core.canonical_conflicts | Canonical signal conflicts | 6 |
corpus.canonical_targets | Canonical target health | 5 |
corpus.sitemap_hygiene | Sitemap vs crawl hygiene | 4 |
core.trust_pages | Real-business trust pages | 6 |
corpus.near_duplicate | Near-duplicate pages | 5 |
core.answer_position | Answer-first structure | 4 |
core.ai_bot_matrix | AI bot policy matrix | 4 |
core.tel_clicktap | Tap-to-call phone link | 2 |
core.hours_markup | Opening hours in structured data | 2 |
core.geo_coordinates | Map-pin data (geo or full address) | 1 |
core.schema_visible_parity | Structured data matches the visible page | 3 |
core.schema_review_integrity | Self-serving review markup | 4 |
corpus.city_swap | City-swapped template pages | 4 |
Amplifier: edges that lift a solid core (38 checks)
| check id | what it verifies | weight |
|---|---|---|
core.llms_txt | llms.txt file | 2 |
corpus.unique_meta | Unique meta descriptions | 4 |
corpus.internal_links | Internal links | 4 |
corpus.anchor_text | Link anchor text | 3 |
amp.question_headers | Question-style headings | 3 |
amp.snippet_eligible | AI Overviews eligibility | 6 |
amp.canonical | Canonical URL | 4 |
amp.open_graph | Social sharing tags | 3 |
amp.heading_order | Heading order | 2 |
amp.hreflang | Language targeting (hreflang) | 2 |
amp.author_byline | Author byline | 3 |
amp.freshness | Honest dates | 3 |
amp.indexnow | IndexNow key | 1 |
amp.field_cwv | Real-user speed data | 2 |
corpus.hreflang_reciprocity | hreflang return links | 2 |
corpus.link_depth | Click depth | 2 |
amp.service_pages | Service page coverage | 4 |
amp.location_pages | Location pages vs doorway risk | 5 |
amp.semantic_tables | Extractable tables and lists | 2 |
amp.title_rewrite_risk | Title rewrite risk | 3 |
amp.site_name | Site name markup | 2 |
amp.citable_facts | Citable sourced facts | 2 |
amp.passage_structure | Passage structure | 2 |
amp.og_image_valid | Social preview image (og:image) | 2 |
amp.robots_directives | Robots directive conflicts and noarchive | 3 |
corpus.orphan_pages | Orphan pages (sitemap vs internal links) | 3 |
corpus.crawl_traps | Crawl traps (parameter and calendar URL explosion) | 2 |
corpus.sitemap_lastmod | Sitemap lastmod accuracy | 2 |
amp.schema_breadcrumb | Breadcrumb markup validity | 3 |
amp.schema_article | Article markup quality | 3 |
amp.schema_product | Product markup quality | 4 |
amp.schema_merchant_fields | Merchant listing fields | 2 |
amp.schema_faq | FAQ markup structure | 2 |
amp.schema_person_author | Author markup quality | 2 |
amp.schema_video | Video markup | 2 |
amp.schema_dates_consistency | Schema date consistency | 2 |
amp.homepage_proof | Homepage proof sentence | 2 |
amp.content_staleness | Content age (18-month staleness) | 2 |
Hygiene: leaks that drain earned authority (41 checks)
| check id | what it verifies | weight |
|---|---|---|
corpus.broken_links | Dead links | 4 |
hyg.https | HTTPS | 4 |
hyg.redirects | Redirects | 3 |
hyg.mixed_content | Insecure assets | 3 |
hyg.image_dimensions | Image dimensions | 2 |
hyg.page_weight | Page speed basics | 2 |
hyg.viewport | Mobile viewport | 3 |
hyg.img_alt | Image alt text | 2 |
hyg.html_lang | Page language | 2 |
hyg.not_found | 404 error handling | 2 |
hyg.host_consistency | One site address | 3 |
hyg.soft_404 | Soft 404 pages | 2 |
hyg.head_validity | Head section integrity | 4 |
hyg.url_structure | URL structure | 3 |
corpus.link_quality | Internal link quality | 3 |
hyg.redirect_quality | Redirect technique | 3 |
hyg.keyword_stuffing | Keyword stuffing | 3 |
hyg.hidden_text | Hidden text | 2 |
hyg.placeholder_text | Placeholder content | 2 |
hyg.favicon | Favicon | 2 |
hyg.server_response | Server response and compression | 2 |
hyg.folklore_flags | SEO folklore on this site | 1 |
hyg.meta_charset | Charset declaration position | 1 |
hyg.multiple_titles | Title element placement | 2 |
hyg.base_href | Base URL override | 1 |
hyg.charset_conflict | Charset agreement (header vs page) | 1 |
corpus.redirected_internal_links | Redirected internal links | 2 |
corpus.url_case_consistency | URL case and trailing-slash consistency | 1 |
hyg.js_navigation | Crawlable navigation links | 2 |
hyg.iframe_main_content | Main content inside iframes | 1 |
hyg.img_lazy_strategy | Image lazy-loading strategy | 2 |
hyg.img_responsive | Responsive images | 2 |
hyg.img_formats | Modern image formats | 1 |
hyg.render_blocking_scripts | Render-blocking scripts | 2 |
hyg.dom_size | Page complexity (DOM size) | 2 |
hyg.third_party_scripts | Third-party scripts | 2 |
hyg.font_delivery | Font delivery | 2 |
hyg.heavy_embeds | Heavy embeds | 2 |
hyg.inline_data_uris | Inline image payloads | 1 |
hyg.schema_syntax | JSON-LD syntax | 2 |
hyg.local_folklore | Local SEO folklore (keyword domains, stuffed names) | 1 |
The 48 Vibe Audit checks (graded per pillar, 30% of the overall)
Security pillar (23 checks)
| check id | what it verifies | weight |
|---|---|---|
sec.secrets_exposed | Exposed secret keys in page source | 10 |
sec.source_maps | Published source maps | 3 |
sec.vuln_libs | Outdated libraries with known CVEs | 5 |
sec.form_action_https | Forms submit over HTTPS | 8 |
sec.tls_cert | TLS certificate validity | 10 |
sec.tls_protocol | Modern TLS protocol | 7 |
sec.https_redirect | HTTP redirects to HTTPS | 7 |
sec.hsts | HSTS (Strict-Transport-Security) | 5 |
sec.csp | Content-Security-Policy | 7 |
sec.clickjacking | Clickjacking protection | 5 |
sec.nosniff | X-Content-Type-Options: nosniff | 4 |
sec.referrer_policy | Referrer-Policy | 3 |
sec.permissions_policy | Permissions-Policy | 3 |
sec.cors_wildcard | CORS not overly permissive | 7 |
sec.server_tokens | Server version not disclosed | 3 |
sec.cookie_flags | Cookie security flags | 5 |
sec.security_txt | security.txt (RFC 9116) | 2 |
sec.dotenv_exposed | .env file not exposed | 10 |
sec.git_exposed | .git folder not exposed | 10 |
sec.spf | SPF email-authentication record | 5 |
sec.dmarc | DMARC email-authentication record | 5 |
sec.sri | Subresource Integrity on third-party scripts | 5 |
sec.exposed_files | No exposed backup/config artifacts | 10 |
Accessibility pillar (18 checks)
| check id | what it verifies | weight |
|---|---|---|
a11y.lang | Page language declared (WCAG 3.1.1) | 6 |
a11y.img_alt | Images have alt text (WCAG 1.1.1) | 8 |
a11y.form_labels | Form fields labeled (WCAG 1.3.1/3.3.2) | 8 |
a11y.page_title | Page has a title (WCAG 2.4.2) | 6 |
a11y.heading_order | Heading levels not skipped (WCAG 1.3.1) | 4 |
a11y.link_name | Links have discernible text (WCAG 2.4.4) | 7 |
a11y.button_name | Buttons have accessible names (WCAG 4.1.2) | 6 |
a11y.viewport_zoom | Zoom not disabled (WCAG 1.4.4/1.4.10) | 6 |
a11y.landmarks | Main landmark present (WCAG 1.3.1/2.4.1) | 4 |
a11y.skip_link | Skip-to-content link (WCAG 2.4.1) | 2 |
a11y.tabindex_positive | No positive tabindex (WCAG 2.4.3) | 3 |
a11y.iframe_title | Iframes titled (WCAG 4.1.2/2.4.1) | 4 |
a11y.autoplay_media | No uncontrolled autoplay (WCAG 1.4.2) | 4 |
a11y.video_captions | Video captions track (WCAG 1.2.2) | 5 |
a11y.table_headers | Data tables have headers (WCAG 1.3.1) | 3 |
a11y.duplicate_id | Unique element ids (legacy WCAG 4.1.1) | 2 |
a11y.aria_misuse | ARIA used correctly (WCAG 4.1.2) | 4 |
a11y.alt_quality | Alt text is meaningful (WCAG 1.1.1) | 4 |
Privacy pillar (7 checks)
| check id | what it verifies | weight |
|---|---|---|
priv.policy_link | Privacy policy linked (GDPR/CCPA) | 7 |
priv.cookie_consent | Cookie consent when tracking (ePrivacy) | 7 |
priv.trackers | Third-party trackers disclosed | 3 |
priv.google_fonts_cdn | Google Fonts self-hosted (GDPR) | 5 |
priv.preconsent_cookies | No tracking cookies before consent (ePrivacy) | 7 |
priv.embed_leaks | No IP-leaking third-party embeds (GDPR) | 5 |
priv.policy_content | Privacy policy has substance (GDPR Art. 13/14) | 5 |
The 23 informational checks (never scored)
Observed and reported only (23 checks)
| check id | what it verifies |
|---|---|
hyg.custom_404 | Helpful 404 page |
hyg.hsts | HSTS header (security signal) |
hyg.nosniff | X-Content-Type-Options (security signal) |
hyg.referrer_policy | Referrer-Policy header (privacy signal) |
hyg.clickjacking | Clickjacking protection (security signal) |
hyg.csp | Content-Security-Policy (security signal) |
core.train_vs_retrieve | AI crawler posture (train vs retrieve) |
amp.llms_full_txt | llms-full.txt reference |
hyg.twitter_card | X (Twitter) card tags (preview signal) |
hyg.feed_discovery | RSS/Atom feed (syndication signal) |
hyg.target_blank_noopener | New-tab link rel=noopener (security etiquette) |
hyg.map_presence | Embedded map (convenience signal) |
hyg.preconnect_hints | Early connection hints (performance signal) |
hyg.schema_howto_deprecated | HowTo markup (retired rich result) |
hyg.cookie_flags | Cookie flags (security signal) |
hyg.permissions_policy | Permissions-Policy header (privacy signal) |
hyg.coop_corp | Cross-origin isolation headers (security signal) |
hyg.server_version_leak | Server version disclosure (security signal) |
hyg.sri_third_party | Subresource Integrity on third-party scripts (security signal) |
hyg.cache_control_html | Cache-Control on the HTML document (delivery signal) |
corpus.service_dead_ends | Service pages without a next step (conversion signal) |
amp.qa_coverage | Q&A markup coverage on question pages (answer-engine signal) |
hyg.offsite_profiles | Off-Google platform links (discovery signal) |