Published in full / ssc-1.2 / 31 checks
The standard we score against, in full.
Every check we run, what it costs a score when it fails, and exactly how that score is calculated. None of it is proprietary: a standard you cannot read is a slogan, and a score you cannot recompute is a sales tactic.
How the score works
You can check our arithmetic.
We publish this for one reason: a score we could quietly adjust would not be worth selling. If you disagree with a finding, the rules below are enough to recompute the number yourself and tell us we got it wrong.
Each category starts at 100 and loses points for every check that fails. The category scores are then combined using the weights below.
penalty = base × (1 + log₁₀(occurrences)), capped per severityOccurrences 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.
What each severity costs
| Severity | What it means | Base | Most it can cost |
|---|---|---|---|
| critical | Stops someone completing what they came to do. | 12 | 26 |
| serious | Makes it substantially harder for some people. | 7 | 16 |
| moderate | A real barrier for some, with a workaround for most. | 3 | 8 |
| minor | Worth fixing; nobody is blocked by it. | 1 | 3 |
What each category is worth
| Category | Why | Weight | Live | Planned |
|---|---|---|---|---|
| Accessibility | It is what we are actually assessing. | 76 | 14 | 6 |
| Security | Cheap to get right, expensive to get wrong. | 13 | 6 | 0 |
| Site health | Broken links and missing policies cost enquiries. | 11 | 4 | 1 |
Plannedchecks are published and weighted here but not yet automated, so no site loses points for them today. A category containing planned checks therefore scores higher than the weights imply — uniformly, for every site, in the site’s favour. There are 7 of them, listed with the rest below and marked.
Scores from different versions of this checklist are not comparable, so every scan records the version that produced it. This page is ssc-1.2. How we run each check, and what we keep as evidence, is on the methodology page.
Accessibility / weight 76 / 20 checks
Accessibility
- A-1.1.1serious
Images have meaningful alternative text
Every image that carries information needs a text description.
- What it costs you
- Someone using a screen reader hears "image" instead of what you are showing them. Search engines are equally blind to it.
- How it gets fixed
- In the CMS or template, add an alt attribute to every image that conveys information — a short, specific description of what it shows, not the filename. Leave alt empty (alt="") on purely decorative images so they are skipped rather than mis-described. Verify by viewing the page with images blocked in the browser: every meaningful image should be replaced by readable text.
- Roughly how long
- a few minutes per image, through the media library where one exists
- A-1.1.1-Mserious
Alternative text is actually useful
The description says what the image shows, not "DSC_0421.jpg".
- What it costs you
- Alt text that exists but says nothing passes every automated tool and helps nobody. A machine cannot tell the difference; a person can.
- How it gets fixed
- Rewrite any alt text that is a camera filename, a keyword list, or a copy of the nearby caption so it instead says what the image shows and why it is there. Read each description as if you could not see the image — does it tell you what is happening? Nothing here needs code, only better words in the same alt field used for A-1.1.1.
- Roughly how long
- a few minutes per image
- A-1.3.1serious
Page structure is marked up correctly
Headings, lists and tables are built as headings, lists and tables — not text styled to look like them.
- What it costs you
- Screen reader users navigate by structure. Without it they read the whole page top to bottom or leave.
- How it gets fixed
- Rebuild the elements axe flagged using real HTML — an actual <ul>/<ol> for lists, an actual <table> with <th> header cells for tabular data — instead of styled elements that only look like a list or table. This usually means editing the page template or theme rather than page content. Verify with the browser accessibility tree inspector: the flagged element should show the correct role (list, table, and so on), not "generic".
- Roughly how long
- half a day, depending on how the template was built
- A-1.3.1-Hmoderate
Heading levels are in order
Headings go h1, h2, h3 without skipping levels.
- What it costs you
- Skipped levels break the outline people use to jump around your page.
- How it gets fixed
- Go through the page top to bottom and set each heading to the level that matches its place in the outline — one h1, then h2 for its major sections, h3 only under an h2 — without skipping a level for visual size alone. Where a heading looks empty, either give it real text or remove the heading markup and style the text a different way. Verify with your browser accessibility inspector or a heading-outline extension: the levels should step down one at a time with no gaps.
- Roughly how long
- a sentence-length change per page — picking the right heading style in the editor
- A-1.4.3critical
Text has enough contrast against its background
Normal text needs a 4.5:1 contrast ratio; large text needs 3:1.
- What it costs you
- 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 it gets fixed
- For each flagged text/background pair, pick a darker text color or a lighter background until the contrast ratio the report measured clears 4.5:1 for normal text or 3:1 for large text, then update the color in the stylesheet or theme settings. A free online contrast checker will confirm the new pair before you ship it. Verify by checking the pair again in the contrast checker — the ratio should read at or above the threshold.
- Roughly how long
- an hour or two, most of it picking new colors
- A-1.4.1moderate
Colour is not the only way information is conveyed
Errors, required fields and status are marked with more than just red or green.
- What it costs you
- Roughly one in twelve men has some colour vision deficiency. If red is your only signal, they miss it.
- How it gets fixed
- For every place color alone marks meaning — an error, a required field, a status badge, a link in a paragraph — add a second signal: an icon, an underline, bold text, or a text label, so removing color removes nothing. Links inside body copy specifically need an underline or a strong contrast difference, not just a different hue. Verify by opening the page with a grayscale filter (most browser dev tools have one) — every piece of information that mattered in color should still be legible.
- Roughly how long
- an hour or two
- A-1.4.4moderate
Text survives being zoomed to 200%
Zooming to twice the size does not cut off or overlap content.
- What it costs you
- Many people browse zoomed in permanently. If your layout breaks, your site is unusable for them.
- How it gets fixed
- Set the browser zoom to 200% and find every place text gets clipped, cut off by a fixed-height container, or overlaps other content, then switch those containers to flexible sizing (min-height, overflow visible, or relative units) instead of a fixed pixel height. Repeat with the OS text-size setting where the platform allows it. Verify by zooming to 200% again — nothing should be cut off, overlapping, or pushed outside the visible page.
- Roughly how long
- half a day, depending on how rigid the layout is
- A-1.4.10serious
No horizontal scrolling at phone width
At 320 pixels wide the page reflows instead of forcing sideways scrolling.
- What it costs you
- More web traffic worldwide now comes from phones than desktops. Sideways scrolling reads as broken and people leave.
- How it gets fixed
- At a 320px-wide viewport, find the element wider than the screen — often a fixed-width image, table, or a container with a hardcoded pixel width — and switch it to a relative width (max-width: 100%, or a percentage) so it shrinks with the screen instead of forcing a sideways scrollbar. Verify by loading the page in a phone-width browser window (or device emulator) and confirming there is no horizontal scrollbar.
- Roughly how long
- a few hours — usually one wide element to track down
- A-2.1.1critical
Everything works with a keyboard alone
Every button, link, menu and gallery can be reached and operated without a mouse.
- What it costs you
- 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 it gets fixed
- For every custom control that only responds to a mouse click (a gallery, a dropdown, a lightbox), add the same behavior on Enter and Space key presses, and make sure Tab actually reaches it — usually by using a real <button> or <a> element instead of a plain <div> with a click handler. Verify by not touching the mouse and tabbing through the whole page — every control a visitor can click should also be reachable and operable this way.
- Roughly how long
- half a day to a day, depending on how many custom widgets the site has
- A-2.1.2critical
No keyboard traps
Focus can always move forward and back out of any component.
- What it costs you
- A trap means the only way out is closing the tab. It is the most hostile failure on this list.
- How it gets fixed
- Find the component that traps focus — usually a menu, modal, or lightbox built without keyboard support — and add an Escape handler that closes it and returns focus to the control that opened it, plus normal Tab and Shift+Tab movement in and out. Verify by tabbing into the component and pressing Escape — focus should land back where it started, and Tab/Shift+Tab should never get stuck cycling in place.
- Roughly how long
- half a day
- A-2.4.1moderate
A skip link lets people jump past the navigation
Keyboard users can skip repeated menus and get to the content.
- What it costs you
- Without it, every page starts with a long tab through the same menu before reaching the content.
- How it gets fixed
- Add a "Skip to content" link as the very first focusable element on the page, hidden until it receives keyboard focus, pointing at the main content landmark. Alternatively, make sure the page uses real header, nav and main landmarks, which screen reader users can jump between without a visible skip link. Verify by pressing Tab once from the address bar — the skip link should appear and, when activated, move focus past the navigation.
- Roughly how long
- an hour or two
- A-2.4.3serious
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.
- What it costs you
- When an open menu leaves focus behind it, keyboard users are typing into a page they cannot see.
- How it gets fixed
- Remove any positive tabindex values, which are almost always the cause, and reorder the HTML — not just the visual CSS layout — so the document order matches the order things should be read and tabbed through. Make sure opening a menu or dialog moves focus into it, and closing it returns focus to the control that opened it. Verify by tabbing through the whole page and confirming focus moves in the same order a sighted visitor would read it.
- Roughly how long
- half a day
- A-2.4.4moderate
Link text says where the link goes
No bare "click here" or "read more" without context.
- What it costs you
- Screen reader users often pull up a list of links alone. A page full of identical "read more" entries gives them nothing to go on.
- How it gets fixed
- Rewrite generic link text — "click here", "read more", "learn more" — so each link's own words say where it goes, for example "read more about our roofing warranty" instead of a bare "read more". Where the visible words must stay short, add a visually-hidden span or aria-label with the fuller destination. Verify with your screen reader's link list (or by reading just the linked words down the page) — each one should make sense without its surrounding sentence.
- Roughly how long
- a sentence per link
- A-2.4.7critical
The focused element is visibly marked
Whatever the keyboard is on has a clear outline. Nobody has removed it in the stylesheet.
- What it costs you
- Removing the focus ring for looks makes keyboard navigation impossible — you cannot see where you are.
- How it gets fixed
- Search the stylesheet for outline:none or outline:0 and remove them, or replace them with a visible alternative — a box-shadow, border, or background change — that appears the moment an element receives focus. Make sure the replacement indicator has enough contrast against what is behind it, not just any visible change. Verify by tabbing through the page — every stop should show a clearly visible marker.
- Roughly how long
- an hour or two
- A-2.5.8moderate
Tap targets are large enough
Buttons and links are at least 24 by 24 pixels.
- What it costs you
- Small targets are missed by anyone with a tremor, and by everyone on a bumpy bus.
- How it gets fixed
- For each undersized button or link, increase its clickable area to at least 24 by 24 CSS pixels — usually by adding padding rather than changing the visible icon or text size — or add at least 24px of clear space around it if the visual size cannot change. Verify by measuring the element in browser dev tools at a 375px-wide viewport, or by trying to tap it accurately on a real phone.
- Roughly how long
- an hour or two
- A-3.1.1minor
The page declares its language
A lang attribute tells assistive tech which language to pronounce.
- What it costs you
- Without it, a screen reader may read English with the wrong accent and rules — sometimes unintelligibly.
- How it gets fixed
- Add lang="en" (or the correct BCP 47 code for the site's language) to the opening html tag in the page template. Most website builders expose this as a language setting in site settings rather than requiring template edits, so check there first. Verify by viewing the page source — the html tag should carry a valid, non-empty lang attribute.
- Roughly how long
- a sentence in the page template — a one-line change
- A-3.3.2critical
Every form field has a label
Each input has a real label element, not just placeholder text.
- What it costs you
- A field with no label gives a screen reader nothing to announce, so someone using one has no way to tell what the box is asking for. Quote and contact forms are where this matters most.
- How it gets fixed
- For every input, select, and textarea the report flagged, add a real label element (or wrap the field in one) connected to that field's id — placeholder text alone does not count. Prioritize the contact, quote, and booking forms first, since those are the ones that cost an enquiry when they fail. Verify with a screen reader or the browser accessibility inspector — each field should announce a real label, not just its type.
- Roughly how long
- an hour or two per form
- A-3.3.1moderate
Errors are identified in text and explain the fix
A rejected form says what was wrong and how to correct it.
- What it costs you
- A red border with no message leaves people guessing. Most of them just give up on the form.
- How it gets fixed
- When a form submission is rejected, show the specific problem in text next to the field it belongs to — not just a red border — and say what would be accepted instead, for example "Enter a valid email address like name@example.com". Move keyboard focus to the first error, or announce it through an aria-live region, so it is not only visible. Verify by submitting the form with one deliberately wrong field and confirming the message is both visible and read aloud by a screen reader.
- Roughly how long
- half a day per form
- A-4.1.2critical
Controls have accessible names
Buttons, links and widgets announce what they do — including icon-only carousel arrows.
- What it costs you
- An unnamed button is announced as just "button". Carousel and lightbox controls are the usual offenders.
- How it gets fixed
- For every icon-only button, link, or widget the report flagged — carousel arrows and lightbox close buttons are the usual culprits — add an aria-label or visually-hidden text describing what it does, for example aria-label="Next slide". Verify by checking the computed accessible name in the browser dev tools accessibility panel — it should read the action, not be blank.
- Roughly how long
- an hour or two
- A-4.1.2-ARIAserious
ARIA is valid, and hidden content is actually hidden
ARIA roles and attributes are used correctly, and anything marked hidden from screen readers cannot still be reached with the keyboard.
- What it costs you
- Broken ARIA is worse than none, and a common cause is a carousel or slider that marks off-screen slides aria-hidden while leaving their links and buttons in the tab order — a keyboard or screen reader user lands on a control they cannot see or use. Pages using ARIA average more errors than pages without it, usually because a plugin applied it wrong.
- How it gets fixed
- Fix each invalid role, attribute, or value axe reports — usually by correcting a typo or removing an attribute that does not apply to that element. Separately, find any aria-hidden="true" container that still holds a focusable link, button, or input — typically off-screen carousel slides — and either remove those elements from the tab order (tabindex="-1", or inert) or stop marking the container hidden while it is still reachable. Verify by tabbing through the page: focus should never land inside something marked aria-hidden, and the accessibility panel should show no invalid ARIA.
- Roughly how long
- half a day, more if the ARIA was applied by a third-party plugin
Security / weight 13 / 6 checks
Security
- S-TLScritical
The site is served over HTTPS
The connection is encrypted and the certificate is valid and current.
- What it costs you
- Browsers now label plain HTTP as "Not secure" in the address bar. Visitors see that before they see you.
- How it gets fixed
- Install a valid TLS certificate for the domain — many hosts and platforms provision one automatically, sometimes behind a toggle in site settings — and confirm the site redirects http:// to https:// automatically. If the certificate is expired or invalid, renew or reissue it through the host or certificate provider. Verify by loading the site and checking for a padlock in the address bar with no warning.
- Roughly how long
- an hour, or a support ticket to your host if the certificate needs reissuing
- S-HSTSmoderate
HTTPS is enforced (HSTS)
The server tells browsers to refuse the unencrypted version.
- What it costs you
- Without it, the first visit can be intercepted before the redirect happens.
- How it gets fixed
- Add a Strict-Transport-Security response header (for example, max-age=31536000; includeSubDomains) in the server or platform header configuration. On Apache, add `Header always set Strict-Transport-Security "max-age=31536000"` to .htaccess; on nginx, add it in the server block; on a website builder that does not expose custom headers, this cannot be fixed there. Verify by checking the response headers of the live site (browser dev tools Network tab) for strict-transport-security.
- Roughly how long
- a few minutes, on platforms that allow custom headers
- S-CSPserious
A content security policy is set
The site declares which scripts it trusts.
- What it costs you
- This is the main defence against an injected script skimming forms.
- How it gets fixed
- Add a Content-Security-Policy response header that names which sources of scripts, styles, and other resources the page trusts, then test the page thoroughly since an overly strict policy can silently break embedded widgets or third-party scripts. On Apache or nginx this is a header configuration change; on a website builder that does not allow custom headers, this cannot be fixed there. Verify by checking the response headers for content-security-policy and confirming the page still works with the policy in place.
- Roughly how long
- half a day to build a policy that does not break the site
- S-FRAMEmoderate
The site cannot be framed by others
X-Frame-Options or frame-ancestors stops someone embedding your site inside theirs.
- What it costs you
- Framing is used to trick visitors into clicking things they cannot see.
- How it gets fixed
- Add either an X-Frame-Options: SAMEORIGIN header or a frame-ancestors directive in the Content-Security-Policy header. On Apache, add `Header set X-Frame-Options SAMEORIGIN` to .htaccess; on a website builder that does not allow custom headers, this cannot be fixed there. Verify by checking the response headers for one of the two.
- Roughly how long
- a few minutes, on platforms that allow custom headers
- S-SNIFFminor
MIME type sniffing is disabled
X-Content-Type-Options: nosniff is present.
- What it costs you
- Stops a browser from guessing that an uploaded file is a script.
- How it gets fixed
- Add an X-Content-Type-Options: nosniff response header. On Apache, add `Header set X-Content-Type-Options nosniff` to .htaccess; on nginx, add it in the server block; on a website builder that does not allow custom headers, this cannot be fixed there. Verify by checking the response headers for x-content-type-options set exactly to nosniff.
- Roughly how long
- a few minutes, on platforms that allow custom headers
- S-STACKserious
No outdated software is publicly advertised
The site does not announce an old CMS or plugin version in its headers or markup.
- What it costs you
- Automated bots scan for exactly these version strings. Advertising one is an invitation.
- How it gets fixed
- Remove or suppress the version string the server sends in the X-Powered-By, Server, or X-Generator headers — most platforms have a setting or a small config change to do this (for example, expose_php off in PHP, or removing a plugin that adds an X-Generator header). Verify by checking the response headers again for a version number after the change.
- Roughly how long
- a few minutes to an hour, depending on the platform
Site health / weight 11 / 5 checks
Site health
- H-LINKSmoderate
No broken links
Every link on the page resolves.
- What it costs you
- A dead link on a services page is a lost enquiry and a bad signal to search engines.
- How it gets fixed
- Update or remove each broken link the report lists, pointing it at the correct current page, or delete it if the destination no longer exists. For links to other sites, confirm the destination has actually moved before assuming your own link is at fault. Verify by clicking the link again and confirming it loads instead of an error page.
- Roughly how long
- a few minutes per broken link
- H-MIXEDserious
No insecure content on a secure page
An HTTPS page does not load images or scripts over plain HTTP.
- What it costs you
- Mixed content breaks the padlock and can be blocked outright by the browser.
- How it gets fixed
- Change every http:// resource the report lists — usually an image or script src — to https://, or to a protocol-relative or root-relative URL so it always matches the page's own protocol. This is often a single find-and-replace across the theme or a plugin setting. Verify by reloading the page and checking the browser console for no more mixed-content warnings.
- Roughly how long
- an hour or two
- H-PRIVACYmoderate
A privacy policy exists and is reachable
If the site collects anything through a form, it says what happens to it.
- What it costs you
- Expected by visitors, required by most analytics and advertising terms of service.
- How it gets fixed
- Write a plain-language privacy policy page describing what information the site collects (through contact forms, analytics, and so on) and what happens to it, then add a link to it — the word "privacy" should appear somewhere in that link's URL or this check will miss it even once the page exists. Link it from the site footer so it is reachable from every page. Verify by scrolling to the bottom of the homepage and confirming a working privacy link is there.
- Roughly how long
- an hour to write, a sentence in the page settings to link it
- H-TITLEmoderate
Pages have unique, descriptive titles
The browser tab and search result say what the page is.
- What it costs you
- The title is the first line of every search result. "Home | Home" wastes it.
- How it gets fixed
- Give each page a specific title in the page's SEO or settings panel — what the page actually is, not "Home" repeated everywhere, and at least a few words long. On a multi-page site, make sure no two pages share the same title. Verify by looking at the browser tab or a search result for the page — it should describe that specific page.
- Roughly how long
- a sentence per page
- H-VIEWPORTserious
Mobile viewport is configured and zoom is not blocked
A viewport meta tag exists and does not disable pinch-to-zoom.
- What it costs you
- Blocking zoom makes the page harder to read for anyone who needs to enlarge text — a site-health basics issue that also happens to be a WCAG 1.4.4 requirement, and still common on older templates that copied an outdated "mobile-friendly" meta tag.
- How it gets fixed
- Edit the viewport meta tag in the page template so it does not include user-scalable=no and does not set maximum-scale below 2 — the simplest fix is often to remove those two parameters entirely and leave only width=device-width, initial-scale=1. Verify by loading the page on a phone or in a mobile emulator and confirming you can pinch-zoom in.
- Roughly how long
- a sentence in the page template — a one-line change
Take this to anyone you like.
Every check above names what to change and how to tell when it is fixed. You do not need us to act on any of it, and a report that could not survive being handed to another developer would not be finished. 24 of these 31 checks are running today.
