Skip to content
Methodology

Every check, and the rule behind it

An audit takes 355 measurements of a website, and 60 rules decide which of them become a finding. Each one is listed below with the exact threshold, what measured it and how confident the reading is. This page is generated from the code that applies the rules, so it cannot describe a check we do not run.

When a check cannot be measured

A site that is down, slow to answer or behind a bot challenge has not shown us anything about itself. We report that check as not measured, leave it out of the score, and say why. It is never a pass and never a fail.

When a fix is checked again

Checks marked "rechecked on request" can be measured again on their own after a fix, by the same rule and to the same standard of evidence as the audit that found them. Checks fed by a business listing or reviews update with the next audit instead.

The same failed measurement, read two ways

In our October 2026 review of 38 audit tools, one graded a well-known, healthy website 0 out of 100 for performance and called it essentially non-functional. The likeliest cause is the tool's own request failing, not the site. This is what each approach tells the reader.

A tool that grades whatever loaded

0/100

"Performance: essentially non-functional." The reader is told their site is broken, and an agency that forwards this report loses the client the first time they open their own website.

SiteAssay

Not measured

"The performance check did not complete, because the site did not answer our measurement in time. It is left out of the score." The rest of the report stands, and nothing in it is a guess.

Speed

Speed checks, the rule behind each and its evidence
Finding Rule Evidence Confidence

Time to First Byte

How quickly the server sends the first byte of the page. Under 800ms feels instant; past 2.5s mobile visitors start leaving.

speed.slow_server_response

Raised when the reading is above 2,500 ms. Live HTTP timing · CDN/cache headers · Google PageSpeed (Lighthouse) Rechecked on request high

Largest Contentful Paint

When the main content becomes visible. Google wants this under 2.5s; it is a direct ranking and conversion factor.

speed.slow_largest_paint

Raised when the reading is above 4,000 ms. Live HTTP timing · CDN/cache headers · Google PageSpeed (Lighthouse) Rechecked on request high

Text Compression

Whether HTML/CSS/JS is compressed (gzip/brotli) before download. Uncompressed pages are far larger and slower on mobile.

speed.no_compression

Raised when the reading is none. Live HTTP timing · CDN/cache headers · Google PageSpeed (Lighthouse) Rechecked on request high

Cumulative Layout Shift

How much the page visually jumps while loading. Lower is steadier; above 0.25 feels broken and misclicks rise.

speed.layout_shift

Raised when the reading is above 0.25. Live HTTP timing · CDN/cache headers · Google PageSpeed (Lighthouse) Rechecked on request high

Search

Search checks, the rule behind each and its evidence
Finding Rule Evidence Confidence

Web design + hosting

presence.no_website

Raised when the business has no website of its own. Business listing high

Indexable (no noindex)

Whether the homepage carries a robots "noindex" directive, which tells search engines to drop it from results entirely.

indexing.homepage_noindex

Raised when the check detects it. Homepage HTML · sitemap/robots probes · structured-data parse Rechecked on request high

Local SEO

rankings.not_ranking

Raised when the reading is 0. Google Business Profile and reviews high

Schema Markup

Structured data that lets Google show rich results (star ratings, FAQs, business info). Competitors with it get the eye-catching listings.

schema.missing

Raised when the check looks for it and does not find it. Homepage HTML · sitemap/robots probes · structured-data parse Rechecked on request high

XML Sitemap

A sitemap.xml helps search engines discover and index every page. Without it, pages can be missed.

indexing.no_sitemap

Raised when the check looks for it and does not find it. Homepage HTML · sitemap/robots probes · structured-data parse Rechecked on request high

Markup Not on the Page

Names, phone numbers and addresses stated in the structured data that the visible page does not show. Google requires markup to describe what a visitor can see.

schema.content_mismatch

Raised when the reading is above 0. Homepage HTML · sitemap/robots probes · structured-data parse Rechecked on request medium

Broken Links

Links on the site that lead to a page that does not answer or answers with an error.

links.broken

Raised when the reading is above 4. lychee Rechecked on request high

Structured Data That Fails To Parse

Whether the page carries JSON-LD structured data that is not valid JSON. Blank when the page has none, which is a separate finding.

schema.unparseable

Raised when the check detects it. Homepage HTML · sitemap/robots probes · structured-data parse Rechecked on request high

LocalBusiness Markup

Whether the homepage carries LocalBusiness structured data, or a local type such as Dentist or Plumber.

schema.missing_local_business

Raised when the check looks for it and does not find it. The homepage, read for local business markup · compared with the Google listing Rechecked on request high

Technical SEO

schema.retired_rich_result

Raised when the reading is above 0. schema Rechecked on request high

Security

Security checks, the rule behind each and its evidence
Finding Rule Evidence Confidence

Exposed Secret Files

Count of publicly reachable sensitive files (.env, .git, phpinfo, open admin/debug dashboards). Any is a critical breach risk, because credentials and source code are downloadable.

exposure.sensitive_files

Raised when the reading is above 0. TLS handshake · HTTP security headers · vulnerability, exposure & blacklist checks Rechecked on request high

Secrets in JavaScript

Count of private API keys (Stripe, AWS, Supabase, tokens) hardcoded into the shipped JavaScript. Any is critical, because the keys are downloadable by anyone.

exposure.leaked_api_keys

Raised when the reading is above 0. TLS handshake · HTTP security headers · vulnerability, exposure & blacklist checks Rechecked on request high

Supabase Database Open

Whether the Supabase database returns real rows to the public anon key shipped in the app, meaning row-level security is off. Any exposed table is a critical breach.

exposure.supabase_rls_off

Raised when the check detects it. TLS handshake · HTTP security headers · vulnerability, exposure & blacklist checks Rechecked on request high

Valid HTTPS Certificate

Whether the SSL/TLS certificate is present and valid. Without it browsers show a full-page "not secure" warning.

tls.invalid_certificate

Raised when the check looks for it and does not find it. TLS handshake · HTTP security headers · vulnerability, exposure & blacklist checks Rechecked on request high

Backend Rules Missing

Whether a Firebase or Convex backend answered an anonymous request with data, meaning its security rules are absent or wide open.

exposure.backend_rules_open

Raised when the check detects it. TLS handshake · HTTP security headers · vulnerability, exposure & blacklist checks Rechecked on request high

Blacklist Status

Whether the site is on a malware/phishing blacklist. A listing means Google warns visitors away and traffic collapses.

blocklist.malware

Raised when the check detects it. Google Business rating & review volume · malware/phishing blacklists Rechecked on request high

Certificate Expiry

Days until the HTTPS certificate expires. When it lapses, every visitor is blocked by a security warning.

tls.expiring_soon

Raised when the reading is below 30 days. TLS handshake · HTTP security headers · vulnerability, exposure & blacklist checks Rechecked on request high

Known Vulnerabilities

Count of known security issues detected. Each is an open door for a hack, defacement or data breach.

scanner.known_vulnerabilities

Raised when the reading is above 0. TLS handshake · HTTP security headers · vulnerability, exposure & blacklist checks Rechecked on request high

Mail Blocklist Status

Whether the domain's mail-sending IP is on an email spam blocklist. A listing means the business's own emails bounce or land in spam.

blocklist.mail_ip

Raised when the check detects it. Google Business rating & review volume · malware/phishing blacklists Rechecked on request high

Vulnerable JavaScript Libraries

Known published vulnerabilities in the JavaScript libraries the site ships.

stack.vulnerable_js_library

Raised when the reading is above 0. js_cve Rechecked on request high

Debug Mode Exposed

Whether error pages leak full stack traces (APP_DEBUG left on), revealing file paths, config and database internals to any visitor.

exposure.debug_mode

Raised when the check detects it. TLS handshake · HTTP security headers · vulnerability, exposure & blacklist checks Rechecked on request high

Forced HTTPS

Whether plain http:// is redirected to https://. Without it, visitors can land on an insecure version and see warnings.

tls.no_https_redirect

Raised when the check looks for it and does not find it. RDAP/WHOIS · DNS records (A/MX/NS, DNSSEC) · redirect & archive checks Rechecked on request high

Mixed (Insecure) Content

Number of insecure http:// resources loaded on a secure page. Browsers block these and flag the page as not fully secure.

tls.mixed_content

Raised when the reading is above 0. TLS handshake · HTTP security headers · vulnerability, exposure & blacklist checks Rechecked on request high

DMARC Record

Tells receivers what to do with mail that fails SPF/DKIM, the key control that stops others impersonating the domain.

email.no_dmarc

Raised when the check looks for it and does not find it. DNS TXT records (SPF, DKIM, DMARC, BIMI) · MX lookup Rechecked on request high

Hosting IP Reputation

Whether the site's hosting IP is flagged for malicious activity in threat intelligence. A flag means bad-neighbour hosting that erodes trust.

blocklist.hosting_ip

Raised when the check detects it. Google Business rating & review volume · malware/phishing blacklists Rechecked on request high

Permissive CORS

Whether the site lets any origin make credentialed cross-origin requests, allowing other websites to read logged-in users' data.

headers.permissive_cors

Raised when the check detects it. TLS handshake · HTTP security headers · vulnerability, exposure & blacklist checks Rechecked on request high

Security Headers Grade

How well HTTP response headers protect against clickjacking, XSS and downgrade attacks. F means the protections are missing.

headers.grade_f

Raised when the reading is F. TLS handshake · HTTP security headers · vulnerability, exposure & blacklist checks Rechecked on request high

SPF Record

Declares which servers may send email for the domain. Without it, mail is easier to spoof and more likely to hit spam.

email.no_spf

Raised when the check looks for it and does not find it. DNS TXT records (SPF, DKIM, DMARC, BIMI) · MX lookup Rechecked on request high

GraphQL Introspection

Whether the GraphQL API exposes its full schema via introspection, handing attackers a complete map of the data model and available operations.

exposure.graphql_introspection

Raised when the check detects it. TLS handshake · HTTP security headers · vulnerability, exposure & blacklist checks Rechecked on request high

Insecure Cookies

Cookies missing Secure/HttpOnly flags, which is a session-hijacking and privacy-compliance risk.

cookies.insecure_flags

Raised when the reading is above 0. TLS handshake · HTTP security headers · vulnerability, exposure & blacklist checks Rechecked on request high

Accessibility

Accessibility checks, the rule behind each and its evidence
Finding Rule Evidence Confidence

WCAG Errors

Number of automated WCAG 2.2 AA failures found by axe-core (contrast, labels, alt text, target size). Each excludes some users and adds ADA/EAA legal exposure.

a11y.wcag_failures

Raised when the reading is above 9. Automated WCAG 2.2 AA checks (axe-core) · alt-text coverage Rechecked on request medium

Image Alt-text Coverage

Percentage of images with descriptive alt text, which helps image SEO and makes the site usable with screen readers.

images.missing_alt

Raised when the reading is below 80%. Automated WCAG 2.2 AA checks (axe-core) · alt-text coverage Rechecked on request high

Technology

Technology checks, the rule behind each and its evidence
Finding Rule Evidence Confidence

Domain Expiry

Days until the domain registration lapses. If it expires, the website and email go dark instantly.

domain.expiring_soon

Raised when the reading is below 45 days. RDAP/WHOIS · DNS records (A/MX/NS, DNSSEC) · redirect & archive checks Rechecked on request high

Up-to-date Software

Whether the platform version is current. Outdated software is the most common way small-business sites get hacked.

stack.outdated_cms

Raised when the check detects it. HTTP fingerprinting · CDN/WAF & mail-provider detection Rechecked on request medium

Mail (MX) Records

Whether the domain can receive email. No MX means the business cannot get mail at its own domain.

email.no_mx

Raised when the check looks for it and does not find it. RDAP/WHOIS · DNS records (A/MX/NS, DNSSEC) · redirect & archive checks Rechecked on request high

Reputation

Reputation checks, the rule behind each and its evidence
Finding Rule Evidence Confidence

Google Rating

Average star rating on Google. Buyers filter out anything under 4.0, so a low rating directly costs calls.

reviews.low_rating

Raised when the reading is below 4. Google Business rating & review volume · malware/phishing blacklists high

Negative Recent Reviews

The share of recent Google reviews that are one or two stars.

reviews.mostly_negative

Raised when the reading is above 30%. Google Business Profile and reviews high

Review Count

How many Google reviews the business has. Too few is a weak trust signal versus more-reviewed competitors.

reviews.too_few

Raised when the reading is below 20. Google Business rating & review volume · malware/phishing blacklists high

Reviews Replied To

Share of recent reviews the business has publicly answered.

reviews.unanswered

Raised when the reading is below 20%. Google reviews captured for this business high

Days Since Last Review

How long ago the newest Google review was left. Shown only when every review on the listing was captured, because from a partial sample the newest one captured may not be the newest there is.

reviews.stale

Raised when the reading is above 180 days. Google reviews captured for this business high

AI visibility

AI visibility checks, the rule behind each and its evidence
Finding Rule Evidence Confidence

AI Crawlers Allowed

Whether robots.txt lets the major AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended) read the site at all.

robots.blocks_ai_crawlers

Raised when the check looks for it and does not find it. Structured-data parse · answerable-content heuristics · llms.txt probe Rechecked on request medium

Answerable Content

Whether the content is structured as clear questions and answers that ChatGPT, Perplexity and Google AI Overviews can cite.

answers.not_answerable

Raised when the check looks for it and does not find it. Structured-data parse · answerable-content heuristics · llms.txt probe Rechecked on request medium

Business Entity Defined

Whether Organization or LocalBusiness schema clearly identifies the business as an entity AI engines can recognise.

schema.missing_entity

Raised when the check looks for it and does not find it. Structured-data parse · answerable-content heuristics · llms.txt probe Rechecked on request medium

Turning visits into calls

Turning visits into calls checks, the rule behind each and its evidence
Finding Rule Evidence Confidence

Clear Call-to-Action

Whether there is an obvious next step (Book, Call, Get a Quote). Without one, interested visitors leave instead of converting.

conversion.no_cta

Raised when the check looks for it and does not find it. Homepage content analysis (CTAs, forms, trust signals, mobile UX) Rechecked on request medium

Lead-capture Form

Whether the site can collect an enquiry. No form means a ready-to-buy visitor has no way to leave their details.

conversion.no_lead_form

Raised when the check looks for it and does not find it. Homepage content analysis (CTAs, forms, trust signals, mobile UX) Rechecked on request medium

Mobile-friendly

Whether the page is built to render usably on phones, which is critical when most local traffic is mobile.

mobile.no_viewport

Raised when the check looks for it and does not find it. Homepage content analysis (CTAs, forms, trust signals, mobile UX) Rechecked on request medium

Tap-to-Call Link

Whether the phone number is a tappable link. On mobile, most callers will not copy a number by hand.

conversion.no_click_to_call

Raised when the check looks for it and does not find it. Homepage content analysis (CTAs, forms, trust signals, mobile UX) Rechecked on request medium

Forms That Submit Nowhere

Forms whose action is "#" or a javascript: placeholder, with no submit handler declared in the markup.

forms.posts_nowhere

Raised when the reading is above 0. Homepage content analysis (CTAs, forms, trust signals, mobile UX) Rechecked on request medium

Reviews / Testimonials

Whether social proof is shown on the page. Visible reviews reassure first-time buyers and lift conversion.

conversion.no_trust_signals

Raised when the check looks for it and does not find it. Homepage content analysis (CTAs, forms, trust signals, mobile UX) Rechecked on request medium

Buttons That Go Nowhere

Call-to-action links on the page whose target is empty, "#" or a javascript: placeholder, with no click handler declared in the markup.

conversion.dead_cta

Raised when the reading is above 0. Homepage content analysis (CTAs, forms, trust signals, mobile UX) Rechecked on request medium

Submit Buttons Outside a Form

Submit buttons not inside a form and not linked to one with a form attribute.

forms.orphan_submit_button

Raised when the reading is above 0. Homepage content analysis (CTAs, forms, trust signals, mobile UX) Rechecked on request medium

Map On The Website

Whether the homepage embeds a Google map.

local.no_map_embed

Raised when the check looks for it and does not find it. The homepage, read for local business markup · compared with the Google listing Rechecked on request high

Content quality

Content quality checks, the rule behind each and its evidence
Finding Rule Evidence Confidence

Thin Homepage Content

Whether the homepage carries too little text for a search engine or an AI assistant to understand what the business does.

content.thin_homepage

Raised when the check detects it. seo Rechecked on request high

JavaScript Console Errors

Number of runtime JavaScript errors and failed requests the browser logged while loading the page.

quality.console_errors

Raised when the reading is above 0. Headless-browser probe (console, coverage, hydration) · homepage placeholder scan Rechecked on request medium

Google Business Profile

Google Business Profile checks, the rule behind each and its evidence
Finding Rule Evidence Confidence

Website Matches The Google Listing

Whether the name, phone and address on the website agree with the Google listing. False on any disagreement; blank when neither side published enough to compare.

nap.mismatch

Raised when the check looks for it and does not find it. The homepage, read for local business markup · compared with the Google listing high

Map Share Of Voice

The share of Local Grid points around the business where it appears in the map results at all, from the latest completed grid.

maps.low_share_of_voice

Raised when the reading is below 25%. The business listing captured during discovery high