Uditus

Our published checklist

Every check we run, what it costs you when it fails, and exactly how the score is calculated. Nothing here is proprietary.

Version ssc-1.0 · 34 checks · effective August 2026

We publish this for a simple reason: a score we could quietly adjust would not be worth selling. If you disagree with a finding, you can check our arithmetic against the rules below and tell us we got it wrong. Some clients have.

How the score is calculated

Each category starts at 100 and loses points for every check that fails:

penalty = base × (1 + log₁₀(occurrences))     capped per severity
Occurrences matter, but with diminishing returns. Forty missing image descriptions is worse than four — but it is usually one template rendered forty times, and one fix clears them all.
SeverityBase penaltyMaximum
critical1226
serious716
moderate38
minor13

The overall score is the weighted average of the four categories:

CategoryWeightWhy
Accessibility70%It is what we are primarily assessing.
Security12%Cheap to get right, expensive to get wrong.
Site health10%Broken links and missing policies cost enquiries.
Performance8%Real, but the most visible and most often already known.

What this version can actually test

10 of the 34 checks below are published and carry weight, but are not yet automated — 24 are in use today. We would rather say so here than let you assume otherwise. Where a check is marked not yet tested, no site loses points for it — including yours, and including your competitors’.

CategoryTested todayNot yet testedWeight
Accessibility14 of 20670%
Security6 of 612%
Site health4 of 5110%
Performance0 of 338%

The consequence worth stating plainly: no site is currently assessed on performance, so every site scores 8 out of 8 there. Every composite score we publish is that much higher than it would be if we tested it. That is the same for everyone, and it is in your favour rather than ours — but you should know it before you read your number. When those checks are automated we will publish a new version rather than quietly changing what your score means.

Two things this score is not

It is not a certification. It is an assessment against this checklist, observed on one date. It says nothing about whether your site complies with the Americans with Disabilities Act or any other law, and we are not qualified to say.

It is not complete. Automated testing catches roughly a third of possible accessibility problems. The checks marked Human review below are the ones a machine cannot settle — which is why a person reads every paid audit before it goes out.

Accessibility 20 checks · 70% of the score

ReferenceCheckSeverityHow tested
A-1.1.1
WCAG 1.1.1
Images have meaningful alternative text
Every image that carries information needs a text description.
Someone using a screen reader hears "image" instead of what you are showing them. Search engines are equally blind to it.
How we test this
  1. Run axe-core with tags wcag2a, wcag2aa, wcag21a, wcag21aa.
  2. Collect violations whose rule id is in `rules`.
  3. occurrences = total failing nodes across those rules.

Fails when: Any node failing any listed rule.

Evidence we record: the exact element, a screenshot of it on your page

Where this check can be wrong:

  • A decorative image with alt="" is correct and axe does not flag it. If one appears, the markup is wrong, not the rule.
  • Images inserted by a third-party widget still count — the visitor cannot tell whose code it is.
seriousAutomated
A-1.1.1-M
WCAG 1.1.1
Alternative text is actually useful
The description says what the image shows, not "DSC_0421.jpg".
Alt text that exists but says nothing passes every automated tool and helps nobody. A machine cannot tell the difference; a person can.
How we test this
  1. List every img, svg[role=img] and CSS-background element carrying meaning, with its alt or accessible name.
  2. Read each one against the content around it.
  3. Flag: camera filenames (DSC_, IMG_, .jpg in the text), keyword lists, text that repeats the adjacent heading verbatim, and "image of" prefixes.
  4. Flag any image that carries information the surrounding text does not already give.
  5. occurrences = images whose alt text does not do its job.

The question our reviewer answers:For each image with alt text: does the text tell someone who cannot see it what the image is doing here — or is it a filename, a keyword list, or a repeat of the words next to it?

Evidence we record: the exact element, a screenshot of it on your page, the reviewer's own note, signed

Where this check can be wrong:

  • A purely decorative image should have alt="". Empty alt is a pass, not a failure.
  • Alt that duplicates an adjacent caption is acceptable when the caption is the description.
seriousHuman review
A-1.3.1
WCAG 1.3.1
Page structure is marked up correctly
Headings, lists and tables are built as headings, lists and tables — not text styled to look like them.
Screen reader users navigate by structure. Without it they read the whole page top to bottom or leave.
How we test this
  1. Run axe-core with the WCAG 2.1 AA tag set.
  2. Collect violations whose rule id is in `rules`.
  3. occurrences = total failing nodes.

Fails when: Any node failing any listed rule.

Evidence we record: the exact element, a screenshot of it on your page

Where this check can be wrong:

  • A layout table with no header cells is bad practice but not this failure. Record it as an observation, not a finding.
seriousAutomated
A-1.3.1-H
WCAG 1.3.1
Heading levels are in order
Headings go h1, h2, h3 without skipping levels.
Skipped levels break the outline people use to jump around your page.
How we test this
  1. Run axe-core with the WCAG 2.1 AA tag set.
  2. Collect violations whose rule id is in `rules`.
  3. occurrences = total failing nodes.

Fails when: A skipped level, a missing h1, or a heading with no text.

Evidence we record: the exact element, a screenshot of it on your page

Where this check can be wrong:

  • A visually hidden h1 is a pass. Confirm it is in the accessibility tree before dropping the finding.
moderateAutomated
A-1.4.3
WCAG 1.4.3
Text has enough contrast against its background
Normal text needs a 4.5:1 contrast ratio; large text needs 3:1.
Low contrast is the single most common failure on the web. It affects anyone with reduced vision, and everyone on a phone in sunlight.
How we test this
  1. Run axe-core with the WCAG 2.1 AA tag set.
  2. Collect violations for color-contrast and color-contrast-enhanced.
  3. Record the measured ratio, both colours and the computed font size from the failure summary.
  4. occurrences = total failing nodes.

Fails when: 4.5:1 for normal text; 3:1 for text at 18pt, or 14pt bold, and larger.

Evidence we record: the exact element, the number we measured, a screenshot of it on your page

Where this check can be wrong:

  • Text over a photograph or gradient: axe reports these as incomplete rather than violations because it cannot compute one background colour. Never convert an incomplete to a finding without a human looking at it.
  • Disabled form controls are exempt from 1.4.3.
  • Text hidden by CSS but still in the DOM. Confirm it is actually visible before reporting it.
criticalAutomated
A-1.4.1
WCAG 1.4.1
Colour is not the only way information is conveyed
Errors, required fields and status are marked with more than just red or green.
Roughly one in twelve men has some colour vision deficiency. If red is your only signal, they miss it.
How we test this
  1. List every place the page signals state: required fields, validation errors, availability, status badges, chart series, map keys, links inside body text.
  2. For each, ask what remains once colour is removed.
  3. Links in running text: confirm they carry an underline or a 3:1 contrast difference against the surrounding text as well as colour.
  4. occurrences = signals conveyed by colour alone.

The question our reviewer answers:If this page were printed in greyscale, which pieces of information would disappear entirely?

Evidence we record: the exact element, a screenshot of it on your page, the reviewer's own note, signed

Where this check can be wrong:

  • Colour reinforcing a label, an icon or a text string is fine. The failure is colour as the *only* carrier.
moderateHuman review
A-1.4.4
WCAG 1.4.4
Text survives being zoomed to 200%
Zooming to twice the size does not cut off or overlap content.
Many people browse zoomed in permanently. If your layout breaks, your site is unusable for them.
How we test this
  1. Load at 1280x1024, then set browser zoom to 200%.
  2. Screenshot the full page.
  3. Detect text clipped by a fixed height, text overlapping other text, and any control pushed outside the viewport.
  4. Repeat with the OS text size at 200% where the platform allows it.
  5. occurrences = distinct regions where content is lost or overlaps.

Fails when: Any content lost, clipped or overlapping at 200%.

Evidence we record: the exact element, a screenshot of it on your page

Where this check can be wrong:

  • Content that reflows into a scrolling region is a pass. Only loss or overlap fails.
moderatenot yet tested
A-1.4.10
WCAG 1.4.10
No horizontal scrolling at phone width
At 320 pixels wide the page reflows instead of forcing sideways scrolling.
Most of your visitors are on a phone. Sideways scrolling reads as broken and they leave.
How we test this
  1. Set the viewport to 320x800 after the page has settled.
  2. Compare document.documentElement.scrollWidth against window.innerWidth.
  3. Fail when scrollWidth exceeds innerWidth by more than 2px, which absorbs sub-pixel rounding.
  4. Identify the widest offending element for the report.
  5. occurrences = 1 per page. The page either reflows or it does not.

Fails when: scrollWidth > innerWidth + 2px at a 320px viewport.

Evidence we record: the exact element, the number we measured, a screenshot of it on your page

Where this check can be wrong:

  • A data table, a map or a code block inside its own scrolling region is explicitly permitted by WCAG 1.4.10. The page fails only when the document itself scrolls sideways.
seriousAutomated (keyboard)
A-2.1.1
WCAG 2.1.1
Everything works with a keyboard alone
Every button, link, menu and gallery can be reached and operated without a mouse.
People with motor impairments, and anyone using assistive tech, navigate by keyboard. A lightbox that only closes on click traps them on the page.
How we test this
  1. Enumerate every element with a click handler, plus every native control.
  2. Tab from the top of the document to the end, recording the element that holds focus at each step.
  3. Any element with a click handler never reached by Tab is a failure.
  4. For each reached control, operate it with Enter and with Space and confirm it does what a click does.
  5. Menus and galleries: confirm arrow keys work where the pattern requires them.
  6. occurrences = controls that cannot be reached or cannot be operated.

Fails when: Any interactive element unreachable or inoperable by keyboard alone.

Evidence we record: the exact element, a screenshot while it has keyboard focus

Where this check can be wrong:

  • A control deliberately removed from the tab order that duplicates another reachable control is a pass. Confirm the duplicate exists and works.
criticalnot yet tested
A-2.1.2
WCAG 2.1.2
No keyboard traps
Focus can always move forward and back out of any component.
A trap means the only way out is closing the tab. It is the most hostile failure on this list.
How we test this
  1. Tab forward through the whole document, capped at 3x the number of focusable elements.
  2. A trap is any point where focus returns to an element already visited without the sequence having wrapped at the document end.
  3. Repeat with Shift+Tab to catch traps that only bite in reverse.
  4. Open every modal, menu and lightbox and repeat inside it. Confirm Escape closes it and returns focus to the control that opened it.
  5. occurrences = distinct components focus cannot leave.

Fails when: Any component keyboard focus cannot exit by Tab, Shift+Tab or Escape.

Evidence we record: the exact element, a screenshot while it has keyboard focus

Where this check can be wrong:

  • A correctly built modal deliberately cycles focus within itself. That is a pass so long as Escape closes it and returns focus. Check Escape before recording a trap.
criticalnot yet tested
A-2.4.1
WCAG 2.4.1
A skip link lets people jump past the navigation
Keyboard users can skip repeated menus and get to the content.
Without it, every page starts with twenty tab presses through the same menu.
How we test this
  1. Run axe-core with the WCAG 2.1 AA tag set and collect bypass and skip-link violations.
  2. During the human pass, press Tab once from the address bar and confirm a skip link becomes visible and works.
  3. occurrences = 1 per page.

Fails when: No skip link, no landmark structure, and no heading structure to navigate by.

Evidence we record: the exact element, a screenshot while it has keyboard focus

Where this check can be wrong:

  • Proper landmark regions satisfy this criterion without a visible skip link. Confirm main, nav and header exist before reporting.
  • A skip link present but permanently hidden even on focus does not count as a pass.
moderateAutomated
A-2.4.3
WCAG 2.4.3
Focus order follows the visual order
Tabbing moves through the page in the order things appear, and focus moves into and out of menus and dialogs correctly.
When an open menu leaves focus behind it, keyboard users are typing into a page they cannot see.
How we test this
  1. Record the tab sequence with each element bounding box.
  2. Compare against reading order: top to bottom, and left to right for the document language.
  3. Flag any backward jump that is not explained by a visual grouping the user can see.
  4. Flag any positive tabindex, which almost always produces this failure.
  5. Open each menu and dialog: confirm focus moves into it on open and returns to the trigger on close.
  6. occurrences = distinct points where the order departs from what is on screen.

Fails when: Focus order that does not preserve meaning and operability.

Evidence we record: the exact element, a screenshot while it has keyboard focus, the number we measured

Where this check can be wrong:

  • A multi-column layout can have a defensible order that is not strictly top to bottom. A human decides whether meaning is preserved.
seriousnot yet tested
A-2.4.4
WCAG 2.4.4
Link text says where the link goes
No bare "click here" or "read more" without context.
Screen reader users often pull up a list of links alone. Twelve identical "read more" entries are useless.
How we test this
  1. Run axe-core with the WCAG 2.1 AA tag set and collect the listed rules.
  2. Additionally extract every link accessible name and group them.
  3. Flag repeated generic names — "read more", "click here", "learn more", bare URLs — pointing at different destinations.
  4. occurrences = links whose purpose cannot be determined from the name.

Fails when: A link with no accessible name, or a generic name reused for different destinations.

Evidence we record: the exact element, a screenshot of it on your page

Where this check can be wrong:

  • Repeated names pointing at the same destination are fine.
  • An aria-label or visually hidden span may already supply context axe cannot see in the visible text. Check the accessible name, not the visible text.
moderateAutomated
A-2.4.7
WCAG 2.4.7
The focused element is visibly marked
Whatever the keyboard is on has a clear outline. Nobody has removed it in the stylesheet.
Removing the focus ring for looks makes keyboard navigation impossible — you cannot see where you are.
How we test this
  1. Grep the stylesheets for `outline:none` and `outline:0` and record where they appear.
  2. Tab to every focusable element. Screenshot each one focused and unfocused.
  3. Diff the two images within the element bounding box plus a 4px margin.
  4. Fail when no pixels change, which means nothing visible marks focus.
  5. Where pixels change, measure the contrast of the indicator against what is behind it.
  6. occurrences = focusable elements with no visible indicator.

Fails when: No visible change on focus; or an indicator below 3:1 against adjacent colour.

Evidence we record: the exact element, a screenshot while it has keyboard focus, the number we measured

Where this check can be wrong:

  • `outline:none` paired with a replacement box-shadow or border is a pass. Judge the rendered pixels, never the stylesheet alone.
  • Browser default focus rings vary. Test in the engine named in the report.
criticalnot yet tested
A-2.5.8
WCAG 2.5.8
Tap targets are large enough
Buttons and links are at least 24 by 24 pixels.
Small targets are missed by anyone with a tremor, and by everyone on a bumpy bus.
How we test this
  1. At a 375px viewport, measure the bounding box of every interactive element.
  2. Fail any target under 24x24 CSS pixels.
  3. Where a target is undersized, measure the distance to its nearest neighbour; 24px of clear spacing satisfies the criterion instead.
  4. occurrences = undersized targets without sufficient spacing.

Fails when: 24x24 CSS pixels, or a 24px spacing offset. WCAG 2.2 SC 2.5.8 Level AA.

Evidence we record: the exact element, the number we measured, a screenshot of it on your page

Where this check can be wrong:

  • Links inline within a sentence are explicitly exempt.
  • A target whose size is fixed by the browser, such as a native control, is exempt.
  • Where an equivalent larger control exists on the same page, the small one is exempt.
moderatenot yet tested
A-3.1.1
WCAG 3.1.1
The page declares its language
A lang attribute tells assistive tech which language to pronounce.
Without it, a screen reader may read English with the wrong accent and rules — sometimes unintelligibly.
How we test this
  1. Run axe-core with the WCAG 2.1 AA tag set and collect the listed rules.
  2. Record the lang attribute actually present, including empty or malformed values.
  3. occurrences = 1 per page.

Fails when: Missing lang, or a value that is not a valid BCP 47 tag.

Evidence we record: the number we measured

minorAutomated
A-3.3.2
WCAG 3.3.2
Every form field has a label
Each input has a real label element, not just placeholder text.
This is the one that costs you money directly. An unlabelled quote form cannot be completed by a screen reader user — they wanted to hire you and could not.
How we test this
  1. Run axe-core with the WCAG 2.1 AA tag set and collect the listed rules.
  2. For every failing field, record which form it belongs to and what that form does.
  3. A failure on a quote, contact or booking form is reported first regardless of order elsewhere — it is the one that costs money.
  4. occurrences = total unlabelled fields.

Fails when: Any input, select or textarea with no programmatically associated label.

Evidence we record: the exact element, a screenshot of it on your page

Where this check can be wrong:

  • Placeholder text is not a label and never satisfies this. Do not drop the finding because the field "looks labelled".
  • A hidden honeypot field used for spam filtering is exempt. Confirm it is genuinely hidden from everyone.
criticalAutomated
A-3.3.1
WCAG 3.3.1
Errors are identified in text and explain the fix
A rejected form says what was wrong and how to correct it.
A red border with no message leaves people guessing. Most of them just give up on the form.
How we test this
  1. Submit each form empty. Then submit it with one deliberately invalid field — a malformed email, a short phone number.
  2. Record what appears: is the error in text, does it name the field, does it say how to fix it.
  3. Confirm the message is announced — an aria-live region, or focus moved to it — not only shown.
  4. Never submit a form on a site we have not been authorised to test. On an unsolicited free scan this check is not performed.
  5. occurrences = forms whose errors are not identified in text.

The question our reviewer answers:When this form rejects something, does it say in words which field was wrong and what would be accepted instead?

Evidence we record: the exact element, a screenshot of it on your page, the reviewer's own note, signed

Where this check can be wrong:

  • Native browser validation messages satisfy this criterion. Confirm they are absent before reporting.
moderateHuman review
A-4.1.2
WCAG 4.1.2
Controls have accessible names
Buttons, links and widgets announce what they do — including icon-only carousel arrows.
An unnamed button is announced as just "button". Carousel and lightbox controls are the usual offenders.
How we test this
  1. Run axe-core with the WCAG 2.1 AA tag set and collect the listed rules.
  2. Record the computed accessible name for each failing control, which is usually empty.
  3. Note which library produced the control where the tech fingerprint identifies one — icon-only carousel and lightbox arrows are the usual source.
  4. occurrences = total controls with no accessible name.

Fails when: Any interactive control whose computed accessible name is empty.

Evidence we record: the exact element, a screenshot of it on your page

Where this check can be wrong:

  • An icon font or SVG may supply a name through aria-label or a title element. Check the computed name rather than the visible content.
criticalAutomated
A-4.1.2-ARIA
WCAG 4.1.2
ARIA is used correctly, or not at all
ARIA roles and attributes are valid and point at elements that exist.
Broken ARIA is worse than none. Pages using ARIA average more errors than pages without it, because it is usually applied by a plugin that got it wrong.
How we test this
  1. Run axe-core with the WCAG 2.1 AA tag set and collect the listed rules.
  2. Record ARIA density from the scan signals — elements carrying aria-* or role, over total elements.
  3. Where density is high and failures cluster in one component, name the library from the tech fingerprint in the report. It points at one fix rather than many.
  4. occurrences = total failing nodes.

Fails when: Any invalid role, invalid attribute, invalid value, missing required attribute or child, or aria-hidden on a focusable element.

Evidence we record: the exact element, a screenshot of it on your page

Where this check can be wrong:

  • aria-hidden on a decorative icon inside a labelled button is correct and axe does not flag it.
seriousAutomated

Security 6 checks · 12% of the score

ReferenceCheckSeverityHow tested
S-TLSThe site is served over HTTPS
The connection is encrypted and the certificate is valid and current.
Browsers now label plain HTTP as "Not secure" in the address bar. Visitors see that before they see you.
How we test this
  1. Fail when the final URL after redirects is not https://.
  2. Navigate with certificate errors NOT ignored, so an invalid or expired certificate fails the navigation.
  3. KNOWN GAP in ssc-1.0: a failed navigation is currently recorded as `unreachable` and the site is skipped, so an expired certificate is not yet reported as this failure. Until the scanner separates the two, a human confirms certificate validity during a paid audit.
  4. occurrences = 1 per site.

Fails when: Not served over HTTPS, or a certificate that is invalid, expired or does not match the host.

Evidence we record: the number we measured, your response headers as we received them

criticalAutomated (headers)
S-HSTSHTTPS is enforced (HSTS)
The server tells browsers to refuse the unencrypted version.
Without it, the first visit can be intercepted before the redirect happens.
How we test this
  1. Read the response headers of the final navigation, lowercased.
  2. Fail when strict-transport-security is absent.
  3. Record the max-age where present, for the report.
  4. occurrences = 1 per site.

Fails when: Header absent. Presence is a pass in ssc-1.0; max-age is recorded but not scored.

Evidence we record: your response headers as we received them

moderateAutomated (headers)
S-CSPA content security policy is set
The site declares which scripts it trusts.
This is the main defence against an injected script skimming your contact form.
How we test this
  1. Read the response headers of the final navigation, lowercased.
  2. Fail when content-security-policy is absent.
  3. occurrences = 1 per site.

Fails when: Header absent. ssc-1.0 scores presence only and does not grade policy strength.

Evidence we record: your response headers as we received them

Where this check can be wrong:

  • A policy delivered by meta http-equiv is not read by this check and would show as a false failure. Confirm against the page source during a paid audit.
  • Report-only mode counts as present here even though it enforces nothing. Say so in the report rather than scoring it differently.
seriousAutomated (headers)
S-FRAMEThe site cannot be framed by others
X-Frame-Options or frame-ancestors stops someone embedding your site inside theirs.
Framing is used to trick visitors into clicking things they cannot see.
How we test this
  1. Read the response headers of the final navigation, lowercased.
  2. Pass when x-frame-options is present, or when content-security-policy contains frame-ancestors.
  3. Fail only when neither is present.
  4. occurrences = 1 per site.

Fails when: Neither x-frame-options nor a CSP frame-ancestors directive.

Evidence we record: your response headers as we received them

moderateAutomated (headers)
S-SNIFFMIME type sniffing is disabled
X-Content-Type-Options: nosniff is present.
Stops a browser from guessing that an uploaded file is a script.
How we test this
  1. Read the response headers of the final navigation, lowercased.
  2. Fail when x-content-type-options is absent or is any value other than nosniff.
  3. occurrences = 1 per site.

Fails when: x-content-type-options is not exactly `nosniff`.

Evidence we record: your response headers as we received them

minorAutomated (headers)
S-STACKNo outdated software is publicly advertised
The site does not announce an old CMS or plugin version in its headers or markup.
Automated bots scan for exactly these version strings. Advertising one is an invitation.
How we test this
  1. Concatenate the x-powered-by, server and x-generator response headers.
  2. Fail when that string contains a version number matching \d+\.\d+.
  3. Record the exact string observed. Report it verbatim and nothing more.
  4. Never test whether the advertised version is actually vulnerable. That is active testing and the scanning policy forbids it.
  5. occurrences = 1 per site.

Fails when: A version number publicly advertised in a response header.

Evidence we record: your response headers as we received them, the number we measured

Where this check can be wrong:

  • A generic `nginx` or `Apache` with no version is not a failure.
  • We report only that a version is advertised. We never state or imply the software is vulnerable, out of date or exploitable — that is a claim we cannot substantiate and it is exactly the projected-risk language the disclaimer forbids.
seriousAutomated (headers)

Site health 5 checks · 10% of the score

ReferenceCheckSeverityHow tested
H-LINKSNo broken links
Every link on the page resolves.
A dead link on a services page is a lost enquiry and a bad signal to search engines.
How we test this
  1. Collect every href on the page in scope.
  2. Issue one HEAD request per unique destination, falling back to a ranged GET where HEAD is refused.
  3. Apply the same 4s per-domain rate limit to third-party hosts. Never fan out.
  4. Fail on 4xx and 5xx. Record 3xx chains without failing them.
  5. Do not follow links into areas requiring authentication, and do not enumerate paths.
  6. occurrences = unique destinations that do not resolve.

Fails when: Any link returning 4xx or 5xx.

Evidence we record: the exact element, the number we measured

Where this check can be wrong:

  • Sites that refuse HEAD, or that block unknown user-agents, produce false failures. Confirm with a ranged GET before reporting a third-party link as broken.
  • A 403 from a third-party host may be blocking us specifically, not a broken link for the visitor.
moderatenot yet tested
H-MIXEDNo insecure content on a secure page
An HTTPS page does not load images or scripts over plain HTTP.
Mixed content breaks the padlock and can be blocked outright by the browser.
How we test this
  1. Collect the src of every img and script, and the href of every link element.
  2. Count those beginning with http://.
  3. occurrences = number of insecure subresources.

Fails when: Any subresource loaded over http:// on an https:// page.

Evidence we record: the exact element, the number we measured

Where this check can be wrong:

  • An http:// URL inside a plain anchor is an outbound link, not mixed content. Only subresources count.
  • ssc-1.0 reads the DOM after load, so content the browser already blocked may not appear. This under-reports rather than over-reports.
seriousAutomated
H-PRIVACYA privacy policy exists and is reachable
If the site collects anything through a form, it says what happens to it.
Expected by visitors, required by most analytics and advertising terms of service.
How we test this
  1. Collect every link href on the page.
  2. Fail when none matches /privacy/i.
  3. occurrences = 1 per page.

Fails when: No link whose URL contains "privacy".

Evidence we record: the number we measured

Where this check can be wrong:

  • A policy linked as "Terms" or "Legal", or reached from a different page, is missed by this check. On a paid audit confirm by hand before reporting it.
  • ssc-1.0 matches the URL, not the link text. A policy at /site-notice would be a false failure.
moderateAutomated
H-TITLEPages have unique, descriptive titles
The browser tab and search result say what the page is.
The title is the first line of every search result. "Home | Home" wastes it.
How we test this
  1. Read document.title.
  2. Fail when it is empty or under 5 characters after trimming.
  3. On a multi-page audit, additionally fail titles duplicated across pages.
  4. occurrences = 1 per page.

Fails when: Empty, or fewer than 5 characters. Uniqueness is only assessed across a paid multi-page audit.

Evidence we record: the number we measured

Where this check can be wrong:

  • A short but genuinely descriptive title on a single-page site can be a pass. A human decides.
moderateAutomated
H-VIEWPORTMobile viewport is configured and zoom is not blocked
A viewport meta tag exists and does not disable pinch-to-zoom.
Blocking zoom is a direct accessibility failure and still common on older templates.
How we test this
  1. Read the content attribute of meta[name=viewport].
  2. Fail when the tag is absent.
  3. Parse the content into key/value pairs — never substring-match it.
  4. Fail when user-scalable is no, 0 or false.
  5. Fail when maximum-scale parses to a number below 2.
  6. occurrences = 1 per page.

Fails when: No viewport meta, or a zoom cap below 200%. The 2x boundary is where WCAG 1.4.4 puts it.

Evidence we record: the number we measured

Where this check can be wrong:

  • maximum-scale=5 or =10 permits zoom and is a pass. An earlier substring test flagged =10 as a failure; it is parsed now.
  • Blocking zoom is a WCAG 1.4.4 Level AA accessibility failure, but ssc-1.0 scores this check under site health. It therefore costs fewer points than its accessibility equivalent would, and on its own it does not make a site count as having an accessibility failure. We think that is the wrong home for it. Moving it changes what a score means, so it waits for a new checklist version rather than being changed underneath you.
seriousAutomated

Performance 3 checks · 8% of the score

ReferenceCheckSeverityHow tested
P-LCPThe main content appears quickly
Largest Contentful Paint under 2.5 seconds.
Every extra second past three loses visitors. On a phone on mobile data it is worse.
How we test this
  1. Run Lighthouse against the page on a simulated mobile device with 4G throttling.
  2. Record the Largest Contentful Paint in milliseconds and which element it was.
  3. Run three times and take the median. A single run is noise.
  4. occurrences = 1 per page.

Fails when: LCP above 2.5s at the median of three throttled mobile runs.

Evidence we record: the number we measured, a screenshot of it on your page

Where this check can be wrong:

  • Our own network conditions are not the client's visitors'. Report the throttling profile alongside the number, always.
seriousnot yet tested
P-CLSThe layout does not jump while loading
Cumulative Layout Shift under 0.1.
Content moving under a finger causes mistaps, and reads as cheap.
How we test this
  1. Run Lighthouse on a simulated mobile device with 4G throttling.
  2. Record Cumulative Layout Shift and the elements that moved.
  3. Median of three runs.
  4. occurrences = 1 per page.

Fails when: CLS above 0.1 at the median of three throttled mobile runs.

Evidence we record: the number we measured, a screenshot of it on your page

Where this check can be wrong:

  • Shift caused by a consent banner the visitor dismisses once is real on first visit but not on later ones. Say which it is.
moderatenot yet tested
P-WEIGHTThe page is not unnecessarily heavy
Total page weight under about 3 MB, images sized for the web.
Uncompressed photographs straight from a camera are the usual cause, and the easiest thing to fix.
How we test this
  1. Sum the transferred bytes of every response, from the network log rather than content-length headers.
  2. List the ten heaviest resources with their types.
  3. For each image, compare intrinsic pixel dimensions against the size it is displayed at — oversized originals are the usual cause and the easiest fix.
  4. occurrences = 1 per page.

Fails when: Total transferred weight above 3 MB.

Evidence we record: the number we measured

Where this check can be wrong:

  • ssc-1.0 sums content-length headers, which misses chunked and compressed responses and under-counts. The Lighthouse figure supersedes it once wired.
moderatenot yet tested

Changes to this checklist

Weights and checks change as the standard does. When they change we publish a new version number rather than editing this page, because scores produced under different versions are not comparable. Every report we issue records the version it was scored against — this one is ssc-1.0.