Methodology
How WebVitalist scores your site
Every number in a report comes from a rule you can read on this page. Nothing here is marketing: the weights, thresholds and limits below are the ones in the code that produces your score, and the technical checks table is verified against that code by a test.
The overall score
A report has up to seven category scores, each 0–100. The overall score is their weighted mean. Copy carries the most weight because it is the part no other tool measures; Security Pass runs on every paid product; the functional category only exists on products that run the Full Test.
| Category | Weight | Comes from | Products |
|---|---|---|---|
| Copy & messaging | 25 % | AI review of the page text, validated against a schema | All products |
| Technical SEO | 20 % | 19 deterministic checks on every audited page | All products |
| Security Pass | 15 % | Passive header, cookie, TLS and leak-path checks on the public URL | All paid products |
| Performance | 20 % | Lighthouse performance category, mobile, via PageSpeed Insights | All products (skipped when Lighthouse is unavailable) |
| UX & conversion | 20 % | AI review of the conversion path, validated against a schema | All products |
| Accessibility | 15 % | Lighthouse accessibility category, mobile, via PageSpeed Insights | All products (skipped when Lighthouse is unavailable) |
| Functional | 20 % | HTTP-level link, image and form checks | Full Test and Fix Pack only |
Renormalisation when a category is missing
Categories that did not run are left out and the remaining weights are scaled back up to 100
%. A category is missing when the product does not include it (Functional on an Audit or
Deep Audit) or when a measurement could not be taken (Lighthouse quota exhausted, in which
case Performance and Accessibility are both skipped and marked as such on the progress
page). Formula: overall = Σ(score × weight) / Σ(weight), over the categories
that produced a number, rounded to the nearest integer.
Worked example
An Audit where Lighthouse was unavailable has Technical 72, Copy 61
and UX 55. The available weights sum to 65 %, so the overall is (72×0.20 + 61×0.25 + 55×0.20) / 0.65 = 63. The missing categories neither help nor hurt.
Each category score is clamped to 0–100 and rounded before it enters the mean. A category that ran but produced no score (for example, Lighthouse returned no accessibility category) is treated as missing.
Technical SEO checks
19 deterministic checks run on the HTML of every audited page. Each
ends in pass, warn, fail or info, and each has a weight.
A pass earns the full weight, a warn earns 40 % of it, a fail earns nothing,
and an informational result (a page with no images) earns the full weight so it cannot lower the
score. The technical score is earned weight / total weight × 100, with a total weight of 33.5.
Severity is how the free scan and report rank a problem: a fail on a check weighing 3 or more is critical; other fails and any warn on a check weighing 2 or more are major; the rest are minor.
| Check | Passes when | Warns / fails when | Weight | Severity |
|---|---|---|---|---|
HTTPS https | The final URL after redirects is served over https://. | Fail: the page is served over plain HTTP. | 3 | Critical |
Page title title | A <title> exists and is 30–65 characters long. | Fail: no <title>. Warn: shorter than 30 or longer than 65 characters. | 4 | Critical |
Meta description meta-description | A meta description exists and is 70–165 characters long. | Fail: no meta description. Warn: shorter than 70 or longer than 165 characters. | 3 | Critical |
H1 heading h1 | Exactly one H1 element. | Fail: no H1. Warn: more than one H1. | 3 | Critical |
Heading structure headings | The page has at least one H2, or has fewer than 300 words. | Warn: more than 300 words of text without a single H2. | 1 | Minor |
Canonical canonical | A <link rel="canonical"> exists and points at the same hostname. | Warn: no canonical link, or the canonical points at a different domain. | 2 | Major |
Indexing robots-meta | No noindex directive in the robots meta tag and robots.txt does not block everything. | Fail: the robots meta tag contains noindex, or robots.txt has "Disallow: /" for all user agents. | 3 | Critical |
robots.txt robots-txt | /robots.txt responds with a text document. | Warn: /robots.txt was not found. | 1 | Minor |
Sitemap sitemap | /sitemap.xml responds, or the first sitemap listed in robots.txt does. | Warn: no sitemap could be found. | 1 | Minor |
Mobile viewport viewport | A <meta name="viewport"> tag is present. | Fail: the viewport meta tag is missing. | 3 | Critical |
Language (html lang) lang | The <html> element has a lang attribute. | Warn: no lang attribute on <html>. | 1 | Minor |
Image alt text img-alt | Every <img> has an alt attribute (an empty alt="" counts). Pages without images are marked informational and neither gain nor lose. | Fail: more than 30 % of images lack an alt attribute. Warn: some images lack one. | 2 | Major |
Structured data structured-data | At least one JSON-LD block with an @type is present. | Warn: no JSON-LD found. | 1 | Minor |
Social sharing open-graph | og:title, og:description and og:image are all set. | Warn: one or more Open Graph tags are missing. | 1 | Minor |
Internal links internal-links | At least 3 internal links and no more than 2 generic anchor texts ("read more", "click here", "here"). | Warn: fewer than 3 internal links, or more than 2 links with generic anchor text. | 1 | Minor |
Content length content-length | At least 150 words of visible text. | Warn: fewer than 150 words. | 1 | Minor |
HTML size html-size | The HTML document is 400 kB or smaller. | Warn: the HTML document is larger than 400 kB. | 1 | Minor |
Server response time ttfb | The HTML arrived within 1,500 ms. | Warn: the server took longer than 1,500 ms to deliver the HTML. | 1 | Minor |
Favicon favicon | A <link rel="icon"> or apple-touch-icon is declared. | Warn: no favicon is declared. | 0.5 | Minor |
Multi-page products
On the Deep Audit, Full Test and Fix Pack the same checks run on every crawled page. The technical score is the plain average of the per-page scores; the report lists the checks for the page you entered in full, plus a per-page summary with the failing checks and every page scoring below 70. robots.txt and sitemap results are looked up once per site and shared by all pages.
Length thresholds (30–65 characters for titles, 70–165 for descriptions) are deliberately wider than the 30–60 and 120–160 we recommend in the fix text, so a check only warns when truncation or emptiness is likely rather than merely possible.
Security Pass
Paid reports add a Security Pass score (0–100) from
12 passive checks on the public URL. The scoring rule is the same
as Technical SEO: earned weight / total weight × 100, with a total weight of 28.5.
A pass earns the full weight, a warn earns 40 %, a fail earns nothing,
and informational results (no cookies, leak probes skipped, HTTPS already in use so we did not
see an HTTP landing page) earn the full weight.
We only HEAD/GET the audited URL and a short allowlist of common leak paths on the same origin, with 3 probes at a time and a 4 s timeout. This is not a penetration test: no port scanning, no authentication, no form submission, no SQL/XSS payloads, no fuzzing.
| Check | Passes when | Warns / fails when | Weight | Severity |
|---|---|---|---|---|
HSTS hsts | HTTPS response sends Strict-Transport-Security with max-age of at least 15,552,000 seconds (180 days). | Fail: header missing, or the page is HTTP. Warn: header present but max-age is shorter than 180 days. | 3 | Critical |
Content-Security-Policy csp | A Content-Security-Policy header is present and does not use * on default-src/script-src or unsafe-eval. | Fail: header missing. Warn: present but uses a wildcard script source or unsafe-eval. This is a sanity check, not a full CSP parser. | 3 | Critical |
Clickjacking protection clickjacking | X-Frame-Options is DENY or SAMEORIGIN, or CSP frame-ancestors is set to something other than *. | Fail: neither header/directive is present, or frame-ancestors is *. Warn: an unusual X-Frame-Options value. | 3 | Critical |
Referrer-Policy referrer-policy | A Referrer-Policy other than unsafe-url / no-referrer-when-downgrade is present. | Fail: header missing. Warn: a policy that can leak full URLs across origins. | 1.5 | Minor |
Permissions-Policy permissions-policy | A Permissions-Policy (or legacy Feature-Policy) header is present. | Warn: header missing. This check never fails; the header is still relatively new. | 1 | Minor |
X-Content-Type-Options x-content-type-options | X-Content-Type-Options is nosniff. | Warn: header missing or not nosniff. | 1 | Minor |
Cookie flags cookies | Every Set-Cookie has Secure, HttpOnly and SameSite. Pages that set no cookies are informational and neither gain nor lose. | Fail: a cookie is missing Secure or HttpOnly, or uses SameSite=None without Secure. Warn: SameSite is missing. Skip: no Set-Cookie header. | 3 | Critical |
HTTPS https | The final URL after redirects is served over https://. | Fail: the page is served over plain HTTP. | 4 | Critical |
HTTP to HTTPS redirect https-redirect | If the audit started on http://, it redirected to https://. If it started on https://, the check is informational. | Fail: the page stayed on HTTP. We do not probe the http:// twin of an https:// URL. | 2 | Major |
Mixed content mixed-content | The already-fetched HTML has no src/href/action (or CSS url()) pointing at http:// on an HTTPS page. | Warn: at least one http:// asset signal. Informational if the page is HTTP or HTML was not available. No extra network requests. | 2 | Major |
Sensitive path exposure leaks | GET of /.git/HEAD, /.env, /.env.local, /wp-config.php.bak and /backup.zip returns 404/403, or 200 with a soft-404 HTML page. | Fail: 200 with body that looks like the secret file. Timeouts and 5xx are informational. robots.txt is not a leak path. Probes are capped and short-timeout. | 4 | Critical |
Technology disclosure tech-disclosure | No X-Powered-By, no versioned Server header, and the HTML snippet does not look like a debug/error page. | Warn: X-Powered-By or a versioned Server header. Fail: the HTML looks like a detailed error or debug page. | 1 | Minor |
Performance and Core Web Vitals
Performance comes from a real Lighthouse run on a simulated mobile device through Google's PageSpeed Insights API, requesting the Performance, Accessibility, Best Practices and SEO categories. The Performance category score (0–100 as Lighthouse reports it) is used unchanged as your performance score. Lighthouse Best Practices and SEO are printed in the report but do not enter the overall.
New to these metrics? How to read a Lighthouse / Core Web Vitals report.
The run is made against the URL you entered. On multi-page products we also request Lighthouse for up to 2 more crawled pages on a best-effort basis, but only the main page's numbers feed the score.
Core Web Vitals thresholds
Where Google has enough real-user data (Chrome UX Report, last 28 days), the report shows field LCP, INP and CLS at the 75th percentile with Google's own classification. We do not re-classify these; the thresholds are Google's:
| Metric | Good | Poor |
|---|---|---|
| Largest Contentful Paint (LCP) | ≤ 2.5 s | > 4 s |
| Interaction to Next Paint (INP) | ≤ 200 ms | > 500 ms |
| Cumulative Layout Shift (CLS) | ≤ 0.1 | > 0.25 |
Anything between the two boundaries is "needs improvement". Sites with little traffic have no field data; the report says so and relies on the lab run.
Lab metric targets
The lab numbers Lighthouse measured are printed next to the target we hold them to. Targets are informational: the score itself is Lighthouse's, not ours.
| Lab metric | Target |
|---|---|
| Largest Contentful Paint | < 2,500 ms |
| First Contentful Paint | < 1,800 ms |
| Total Blocking Time | < 200 ms |
| Cumulative Layout Shift | < 0.1 |
| Speed Index | < 3,400 ms |
| Server response time (TTFB) | < 800 ms |
| Total page weight | < 1.5 MB |
We also list up to 8 Lighthouse opportunities that save at least 100 ms, sorted by estimated savings. If PageSpeed Insights is unavailable or its quota is exhausted, the Performance and Accessibility steps are skipped, the overall is renormalised, and the report says so.
Accessibility
The accessibility score is the Lighthouse Accessibility category from the same mobile run, unchanged. It is an automated audit (axe-core rules: contrast, names and labels, ARIA usage, document language, heading order and similar) and can only ever find a subset of real accessibility problems. The report lists up to 12 failing audits by title. Manual and informational Lighthouse audits are excluded.
Independently of Lighthouse, our own HTML analysis counts form fields without labels and buttons without an accessible name; these counts are handed to the AI review as evidence and to the Full Test as functional issues, but they do not change the accessibility score.
Copy & messaging and UX & conversion
These two categories are the model-generated part of the report. A language model acting as a CRO consultant receives: the structured signals we extracted from the page (title, meta, headings, CTA candidates, link and image counts, structured data types), the visible text (up to 14,000 characters), the failing technical checks with their fixes, the Lighthouse summary, and – on multi-page products – the title, H1 and word count of every crawled page. It also receives the goal, notes, platform and competitor URL you gave in the wizard.
What it must return
The answer has to match a strict schema (defined with Zod) or it is rejected and retried:
- Two scores, 0–100, one for copy and one for UX. The prompt calibrates them: 90–100 excellent, 70–89 good with clear gaps, 40–69 significant problems, below 40 fundamentally broken.
- 3–7 findings per category, each with a title, the evidence on the page that shows it, why it matters, a concrete recommendation, and an impact and effort rating.
- Ready-to-paste rewrites: title (30–60 characters), meta description (120–160), H1, hero sub-heading and primary CTA text.
- A 30-day action plan in three blocks (week 1, week 2, weeks 3–4) with 2–6 items each, combining its own findings with the technical and performance items it was given.
- An executive summary and the language the report is written in.
How it is validated
We ask the model for structured output at temperature 0.4 with up to two retries. If the provider cannot produce a schema-conforming object, we fall back to a plain-text request that must contain only JSON, extract it, and validate it against the same schema. Any response that still fails validation fails the audit, which triggers an automatic refund rather than a partial report. The prompt forbids inventing facts about the business, requires every finding to quote evidence, and tells the model not to repeat purely technical items that the deterministic checks already cover.
The report is written in the language of the page (detected from the lang attribute and the visible text), so rewrites can be used directly. In demo deployments the model
is replaced by deterministic fixtures derived from the fetched page and the report is labelled
accordingly.
How the crawl works
Multi-page products discover pages by breadth-first search from the URL you entered (plus
any extra URLs you listed in the wizard). Only same-origin links that look like HTML pages
are followed; robots.txt rules for User-agent: * are honoured with
Google's longest-match semantics, and pages you disallow are skipped, not fetched. The
crawler fetches 4 pages at a time with a 10 s
timeout per page and stops after 90 s even if the page cap
has not been reached. Responses are read up to 2 MB.
| Product | Pages crawled | Functional test | Lighthouse |
|---|---|---|---|
| Audit | 1 (no crawl) | No | Mobile, main page |
| Deep Audit | up to 15 | No | Mobile, main page + 2 best-effort |
| Full Test | up to 25 | Yes | Mobile, main page + 2 best-effort |
| Fix Pack | up to 25 | Yes | Mobile, main page + 2 best-effort |
Site-wide issues
After the crawl we compare pages with each other. Each issue below costs 12 (high), 6 (medium) or 3 (low) points off a crawl health score that starts at 100 and cannot fall below 40. That crawl score is shown on the progress page and its issues appear in the report; it is not one of the weighted categories, because the same problems already lower the per-page technical scores.
| Issue | Severity | Meaning |
|---|---|---|
fetch-failed | high | A queued page could not be fetched at all. |
broken-page | high | A crawled page answered with HTTP 4xx or 5xx. |
missing-title | high | A crawled page has no <title>. |
thin-page | medium | A page has fewer than 150 words of text. |
redirect-chain | medium | Reaching a page took two or more redirects. |
mixed-content | medium | A page on an HTTPS site ended up served over HTTP. |
duplicate-title | medium | Two or more pages share the same title. |
duplicate-description | low | Two or more pages share the same meta description. |
What the Full Test actually does
Today the functional test is an HTTP-level inspection, not a real browser.
We parse the HTML of the page you entered, collect every link, button with an onclick navigation, image and form, and then:
- request up to 150 internal links and record every 4xx/5xx or connection error;
- request up to 60 images and flag errors and HTTP images on HTTPS pages;
- request up to 40 external links and flag 4xx answers (5xx from third parties is ignored as noise);
- inspect every form for an action, a method, labelled fields, named required fields, a submit button and an HTTPS target – forms are never submitted;
- list dead anchors (
href="#",javascript:void, malformed mailto/tel).
Each request has an 8 s timeout, runs 4 at a time, and the whole step stops after 120 s. The functional score starts at 100, loses 8 points per high, 4 per medium and 2 per low issue, and cannot fall below 20.
| Issue | Severity | Meaning |
|---|---|---|
broken-link | high / medium | Internal link returned 5xx (high) or 4xx (medium). |
form-password-get | high | A password field inside a GET form. |
form-no-submit | high | A form without any submit button. |
broken-image | medium | An <img> whose source returned an error. |
mixed-content | medium | Form action or image loaded over HTTP on an HTTPS page. |
form-missing-action | medium | A form without an action attribute. |
form-missing-label | medium | A visible form field without a label, aria-label or aria-labelledby. |
form-required-no-name | medium | A required field that has no name, so it can never be submitted. |
form-missing-method | low | A form without an explicit method. |
button-no-type | low | A <button> inside a form without a type attribute. |
dead-anchor | low | href="#", javascript:void, or a malformed mailto:/tel: link (first 20 listed). |
external-broken | low | An external link returned HTTP 4xx. |
Because no browser is involved, the "JavaScript errors" and "failed requests" counters in a
Full Test report currently reflect only the HTTP probes above: JavaScript is not executed,
console errors are not captured, and buttons that navigate via framework code rather than a
link or onclick are not exercised. A headless-browser version (Cloudflare Browser
Rendering) is prepared in the pipeline and will replace this step when enabled; until then, read
the Full Test as a thorough link, image and form audit.
Deterministic vs model-generated
Two audits of the same unchanged page should give the same deterministic numbers. The AI categories can differ between runs by a few points, which is why they are calibrated with explicit bands and asked to ground every finding in quoted evidence.
| Part of the report | How it is produced |
|---|---|
| Technical SEO score and checks | Deterministic rules on the fetched HTML |
| Security Pass score and findings | Deterministic rules on response headers, cookies, TLS signals and a few leak-path GETs |
| Performance, accessibility, lab metrics, opportunities | Google Lighthouse via PageSpeed Insights (external, may vary slightly run to run) |
| Field data (LCP, INP, CLS) | Chrome UX Report, as published by Google |
| Crawl and functional issues | Deterministic rules on HTTP responses |
| Platform detection | Deterministic signatures in HTML and headers |
| Copy score, UX score, findings, rewrites, action plan, summary | Language model, schema-validated, grounded in the data above |
| Fix Pack code snippets | Language model, prompted with the detected platform and the findings |
Score bands
Every score – overall, per category, per page and in the free scan – is coloured and labelled with the same three bands:
| Label | Range | Rule |
|---|---|---|
| Good | 80–100 | score ≥ 80 |
| Needs work | 50–79 | 50 ≤ score < 80 |
| Poor | 0–49 | score < 50 |
Scores in the "Needs work" band are the ones most worth acting on: they usually mean a handful of specific, fixable problems rather than a rebuild.
The free scan
The free scan fetches one page with an 8 s budget, runs the 19 technical checks above and detects the platform. Its score is the technical score exactly as described here – no Lighthouse, no crawl, no AI. The 3 most severe issues are shown in full (ranked by severity, then weight, then check order); the rest are listed by title only. A completed scan of the same URL is reused for 6 hours.
What we do not measure
- Rankings, keywords and backlinks. We do not query search engines or link databases. The report tells you why a page may struggle to rank, not where it ranks.
- Traffic and conversion rates. We have no access to your analytics; the UX score is an expert review of the conversion path, not a measurement of it.
- Logged-in, paywalled or geo-restricted content. We see what an anonymous visitor and Googlebot see.
- JavaScript execution. Our own checks read the server-rendered HTML. Lighthouse does render the page, so performance and accessibility reflect the rendered result, but the technical checks and the crawl do not see client-side-only content.
- Desktop. Lighthouse runs on a simulated mobile device only.
- Active security testing. Security Pass is a passive public-URL review (headers, cookie flags, TLS, a few leak paths). It is not a pentest, authenticated scan, or certificate deep-inspection.
- Every page of a large site. Crawls are capped per product (see above); site-wide template problems are caught because they repeat, but a broken page outside the crawl will not be.
- Manual accessibility. Automated audits find a fraction of WCAG issues; the report is not a conformance statement.
Something unclear or wrong on this page? Email hello@webvitalist.com. Last updated 2026-09-13.