What we check
69 checks across 7 categories. Each one below links to a full guide on why it matters and how to fix it.
What a check is
A fixed rule with a stated threshold, not an opinion. Each one names the exact signal it reads, so you can check the same thing by hand and get the same answer. All 69 are measured from the page itself and make up the score. The 11 practice guides listed after them are guides to engineering practices a crawler cannot see, such as keeping a staging environment, and the score does not count them.
Three outcomes, not two
A check passes, fails, or reports that we could not determine it. The third is the one that matters: a check we could not settle is never counted as a pass, and never moves your score in either direction. A scanner that quietly turns "we did not look" into a green tick is the one to distrust.
How it reaches the score
Every site starts at 100 and each failed check deducts a fixed amount by severity, with a cap per category so one weak area cannot sink the whole number. The arithmetic is public. See exactly how the score is produced.
Exposure 9
Rotate the exposed Stripe secret key
A live Stripe secret key can issue refunds, create charges, and read customers' payment and order history: whoever holds it can act as the business, not just view its data.
Rotate the exposed AWS access key
An AWS access key inherits whatever permissions are attached to it, which can mean reading files from storage buckets, spinning up billable compute, or altering infrastructure outright.
Revoke the exposed private key
A private key is the credential a certificate, SSH host, or signing system trusts completely: holding it lets an attacker impersonate that system, decrypt its traffic, or sign as it.
Revoke the exposed GitHub token
A GitHub token inherits its scope's permissions, which can include reading private source code, pushing commits, or reading other secrets stored in the repository or its CI pipeline.
Revoke the exposed Slack token
A Slack token can read and post messages in every channel it can reach, letting an attacker read private conversations or impersonate a workspace member.
Rotate the exposed SendGrid API key
A SendGrid API key can send email as the domain's verified sender, which is enough to run a convincing phishing campaign that looks like it came from a trusted source.
Rotate the exposed Supabase service-role key
A Supabase service_role key bypasses row-level security entirely, granting full read and write access to every table in the database rather than the narrow slice an authenticated user is meant to see.
Restrict or rotate the exposed Google API key
An unrestricted Google API key lets anyone who finds it make billable calls against the associated project, running up usage charges or exhausting quota that other features depend on.
Stop shipping source maps publicly
A published source map republishes the original, unminified source (including comments and internal structure never meant to ship), making it far easier to find other vulnerabilities in the same codebase.
Security 19
Serve the site over HTTPS
Without HTTPS, browsers flag the site as "Not Secure" and all traffic, including passwords and payment details, travels in plaintext, exposing customers to interception and eroding trust.
Upgrade vulnerable JavaScript libraries
Known vulnerabilities in an old library version are public, often with ready-made exploits, so attackers scan for them at scale. A vulnerable jQuery or similar library can let an attacker run script in your visitors' browsers (XSS) even when your own code is correct.
Enable HSTS
Without HSTS, a user's first visit or any link they click can be silently downgraded to plain HTTP by an attacker on the network, exposing them to session hijacking even though HTTPS is available.
Fix the Strict-Transport-Security max-age
A Strict-Transport-Security header only protects repeat visitors for as long as its max-age lasts, and a header with no valid max-age at all is ignored outright by browsers. Either state (expired, deliberately zeroed out mid-rollback, or malformed) leaves every visitor as exposed to a downgrade attack on their next visit as if the header had never been sent, even though it's present in every response.
Add a Content-Security-Policy header
Without a Content-Security-Policy, the browser will run any script that ends up on the page, including ones an attacker injects, which is the primary way customer data gets stolen and sessions get hijacked.
Enforce the existing Content-Security-Policy
A report-only policy only logs violations; it does not stop a malicious script from running. The hard part (defining the policy and watching it against real traffic to catch breakage) is already done, so the remaining risk is closed by a one-line header rename, not a redesign.
Add X-Content-Type-Options header
Without nosniff, browsers may reinterpret a file as a different type, for example treating an uploaded image as executable JavaScript, which attackers can exploit to run malicious scripts.
Add clickjacking protection
Without clickjacking protection, an attacker can embed the site in an invisible iframe and trick users into clicking real buttons (like "confirm payment") while they believe they are interacting with another page.
Add a Referrer-Policy header
Without a Referrer-Policy, full page URLs (which may contain session tokens, search terms, or internal paths) are leaked to every third-party site a user navigates to or loads a resource from.
Tighten the Referrer-Policy value
unsafe-url sends the full page URL (including query strings, which can carry session tokens, search terms, or internal paths) to every destination a user navigates to or loads a resource from, even when that destination is reached over a downgraded, insecure connection. It is a one-line value change, not a missing header.
Add a Permissions-Policy header
Without a Permissions-Policy, any script running on the page, including third-party scripts and ads, can request access to the camera, microphone, or location, widening the damage a compromised script can do.
Migrate Feature-Policy to Permissions-Policy
Feature-Policy was renamed and restructured as Permissions-Policy years ago, and current Chromium-based browsers no longer read the old header at all: a site that only ships Feature-Policy is protected in no browser that matters today, even though the restriction was correctly designed once. The syntax is a near-literal translation, so the fix is a rename with a small syntax change, not a redesign.
Mark cookies as Secure
Cookies without the Secure attribute can still be sent over an unencrypted connection if the browser is ever made to request the site over plain HTTP, exposing whatever value the cookie holds to anyone on the same network.
Ask the tracking vendor to mark their cookies Secure
These cookies are written by third-party tracking scripts running on the site (Google Analytics, Google Ads, Microsoft Clarity, Meta Pixel, Microsoft Advertising, and similar), not by the site's own server. "Add Secure to the cookies the app sets" does not apply, because the app never sets them; the vendor's script does, and the vendor's own configuration controls the attributes it uses.
Mark cookies as HttpOnly
Cookies without HttpOnly are readable by any JavaScript on the page, so a single XSS bug is enough for an attacker to steal session cookies and take over accounts.
Stop exposing server software versions
Advertising exact server or framework versions gives attackers a shortcut to find and exploit known vulnerabilities for that specific version, without any extra reconnaissance.
Fix mixed content
Mixed content (HTTP resources loaded on an HTTPS page) is blocked or flagged by modern browsers and gives attackers a way to tamper with an otherwise-secure page by intercepting the insecure resource.
Let the CSP allow what the page loads, or stop loading it
A request the page's own Content-Security-Policy blocks never arrives: an analytics pixel stops counting, a font falls back, a widget stays empty. The browser logs it as an error, which reads like a bug in the code or a service being down, when the cause is one line in the policy.
Get the report-only CSP ready to enforce, safe directives first
A report-only policy stops nothing. Renaming it to an enforcing header is only safe once its violation reports have shown what it would block, and only useful once its script rules no longer allow 'unsafe-inline' or 'unsafe-eval'. A few directives carry no such risk and protect the page today.
Performance 10
Reduce page weight
Heavier pages take longer to load, especially on mobile networks, and slow load times directly correlate with higher bounce rates and lower conversion.
Reduce the number of requests
Every extra request adds latency, especially on slower connections; an excessive request count is a common, fixable reason pages feel sluggish even when total size looks fine.
Reduce third-party request volume
On sites already served over HTTP/2 or HTTP/3, first-party bundling stops being the dominant performance cost: third-party tags (analytics, ads, chat widgets, fonts) usually are, and unlike first-party code the owner cannot bundle them at build time, only choose to run fewer of them.
Optimize large images
Oversized images are one of the single biggest, easiest-to-fix causes of slow pages, and slow pages lose visitors before the content even renders.
Resize the oversized images already in a modern format
An oversized image is still wasted bytes on every load even when its format is already efficient: a modern format compresses better per pixel, but delivering an image far larger than its display size throws that saving away.
Speed up page load time
Slow page loads are one of the strongest predictors of visitors leaving before the page even finishes loading, directly costing traffic and conversions.
Enable text compression
Serving HTML/JS/CSS uncompressed can multiply transfer size several times over, directly slowing every page load for every visitor.
Add cache-control headers to static assets
Without cache headers, returning visitors re-download the same images, scripts, and stylesheets on every visit, wasting bandwidth and slowing repeat page loads unnecessarily.
Reduce render-blocking resources
Render-blocking CSS and JS delay the moment visitors see anything on screen, making the site feel slow even when total page weight is reasonable.
Give images their size, and load them at the right time
An image with no size makes the page jump when it arrives, which visitors notice and search engines measure (layout shift). Images below the fold that load eagerly compete with the first screen for bandwidth, and a lazily loaded first-screen image makes that screen wait.
SEO 20
Add a page title
Without a page title, search engines have no reliable label to show in results and browser tabs are blank, hurting both click-through rate and basic usability.
Fix page title length
Titles that are too short waste an opportunity to describe the page, and titles that are too long get truncated with '...' in search results, hiding the message you're trying to send.
Add a meta description
Without a meta description, search engines auto-generate a snippet from the page's content (often an awkward excerpt), reducing the chance a searcher clicks through.
Fix meta description length
A meta description that's too short under-sells the page, and one that's too long gets cut off in search results. Both reduce click-through rate.
Use exactly one H1 per page
Multiple or missing H1s confuse search engines and screen readers about what the page's main topic actually is, diluting SEO relevance and hurting accessibility.
Add a viewport meta tag
Without a viewport tag, mobile browsers render the page at desktop width and shrink it, making text unreadable and hurting both mobile usability and Google's mobile-first ranking.
Add a canonical link
Without a canonical tag, search engines can split ranking signals across near-duplicate URLs (with tracking params, trailing slashes, etc.), diluting the page's authority.
Allow the page to be indexed
A noindex directive tells search engines to leave the page out of results entirely, and a robots.txt Disallow stops them fetching it in the first place. If either isn't intentional, the page and any traffic or leads it could generate are invisible to search.
Publish a valid robots.txt
robots.txt is the first file search engines and AI crawlers ask for. Without a real one they get no crawl rules and no pointer to your sitemap, and a site that answers with an HTML page instead looks misconfigured to them.
Add an llms.txt file
AI assistants increasingly answer questions about businesses directly. An llms.txt gives them a concise, accurate summary and the right links, instead of leaving them to guess from pages built for people.
Add a language attribute
Without a declared language, search engines may serve the page to the wrong locale's audience and screen readers may mispronounce content, hurting both reach and accessibility.
Add Open Graph tags
Without Open Graph tags, links shared on social platforms and chat apps show a generic or broken preview, which measurably reduces click-through on shared links.
Add a favicon
A missing favicon makes the site look unfinished or untrustworthy in browser tabs, bookmarks, and history (often one of the first things a visitor notices).
Add an Open Graph image
Links shared without an og:image render as a plain text card on social platforms and chat apps, and a card with an image draws far more clicks than one without.
Stop serving your home page twice
When / and /en/ serve the same page and each calls itself canonical, search engines see two copies and split the ranking between them.
Fix skipped heading levels
A heading that jumps from h1 to h3 with no h2 leaves search engines and screen readers with a broken document outline, weakening topical structure and making the page harder to navigate non-visually.
Add structured data
Structured data is what lets search engines show rich results such as review stars, breadcrumbs, and FAQ accordions, which take up more space and earn a higher click-through rate than a plain result.
Point your canonical, share tags and sitemap at your own domain
A canonical or sitemap naming another host tells search engines to rank that host instead of your domain, so your own pages can drop out of results and shared links show the wrong address.
Redirect your other hosts to your main domain
The same site on two hosts splits its search ranking and links between them, and visitors can end up bookmarking or sharing the wrong address.
Add an hreflang x-default
Without an x-default, search engines guess which language version to show everyone outside your listed languages, often the wrong one.
Accessibility 2
Add a language attribute
Without a declared language, screen readers may mispronounce every word on the page, making the site effectively unusable for blind and low-vision visitors.
Add alt text to images
Images without alt text are invisible to screen reader users and to search engines, and in many jurisdictions accessible images are a legal requirement, not just best practice.
Runtime Errors 4
Fix console errors
Console errors often signal broken functionality (failed API calls, broken integrations) that users experience as things silently not working, even if the page still loads.
Fix uncaught JavaScript errors
Uncaught JavaScript exceptions can halt script execution partway through, breaking forms, navigation, or interactive features for real users without any visible warning.
Fix failed network requests
A request that returns 4xx/5xx, or that never reaches a server at all, means something the page depends on (an API, an image, a script) is not arriving, which can silently degrade or break the user experience.
Fix the hydration mismatch
When the server and the browser render different pages, visitors see content jump or flash as the framework corrects it, and parts of the page can stop responding until it does.
Best Practices 5
Add an HTML5 doctype
Without a doctype, browsers render the page in "quirks mode", which can cause inconsistent layout and CSS behavior across browsers.
Declare a character encoding
Without a declared charset, browsers may guess the encoding incorrectly, causing special characters, accents, or symbols to render as garbled text.
Redirect HTTP to HTTPS
If HTTP requests aren't redirected, visitors and search engines who land on the insecure URL stay on it, exposing them to interception and splitting SEO signal between the HTTP and HTTPS versions.
Add a responsive viewport tag
Without a responsive viewport tag, the page renders at desktop width on phones, forcing visitors to pinch and zoom, which drives them away.
Fix HTTPS on your www/apex twin
Visitors who type the other form of your domain get a browser security error instead of your site, and most will not try again.
Practice guides 11
Not checks, and not scored: guides to engineering practices a crawler cannot see, such as keeping a staging environment, and the score does not count them.
Run your tests automatically on every change (CI)
Without CI, regressions reach production because nothing verifies changes automatically; CI turns "hope it works" into "proven before merge".
Set up dependency vulnerability scanning
Most breaches exploit known vulnerabilities in outdated dependencies; without automated scanning these sit unnoticed until someone exploits them.
Set up a staging environment
Without a staging environment, every change is tested for the first time in production, turning routine deploys into high-risk events that can take the live site down.
Add uptime monitoring & alerting
Without uptime monitoring, outages and errors are usually discovered by customers complaining rather than by the team, which extends downtime and erodes trust.
Establish a regular release cadence
Shipping less than once a month means fixes and improvements pile up, changes get riskier and harder to review, and the team loses the ability to respond quickly to bugs or opportunities.
Keep up security hardening
Security posture erodes silently as new code, third-party scripts, or config changes land, so a clean check today does not guarantee a clean check next quarter.
Keep an eye on performance
Performance regressions tend to creep in one image or script at a time, so a fast site today can quietly slow down without ongoing checks.
Keep accessibility standards up
Accessibility is easy to regress when new components or content are added without the same scrutiny as the initial build, quietly locking out users who rely on assistive tech.
Add real-user performance monitoring
Lab scores miss what real users on real devices and networks experience; field data is what Google ranks on and what actually affects conversions.
Connect Google Search Console
Without Search Console you are blind to indexing errors, manual actions, and the queries that bring you traffic.
Add accessibility testing to your process
Inaccessible sites exclude real users and carry legal risk; automated scans plus a screen-reader pass catch most issues cheaply.
Ready to see where you stand?
Scan your site and get your Engineering Score with a prioritized roadmap in under a minute, no signup required.
