ActiScore
← ActiScore
Published rubric

How ActiScore scores a website

Every check, what it deducts, and whether it rests on a published specification, a documented convention, or an explicit judgment call. Nothing here is a trade secret — a score a prospect can audit is the only kind that survives being argued with.

Rubric version: v3 · Last updated 2026-08-16

This document exists so that any score ActiScore produces can be explained, challenged and independently verified. If a prospect disputes a grade, this is the page to hand them.

It is deliberately explicit about which checks rest on published standards, which rest on industry convention, and which are ActiScore's own editorial judgment. Conflating those three is how scoring tools lose credibility.

---

1. How a score is produced

``` fetch page → extract signals → apply deduction table → weight categories → grade (deterministic) (deterministic) ```

1. The target page is fetched server-side once, following up to 5 redirects, over ports 80/443 only, capped at 5 MB, HTML content types only. 2. Signals are extracted from the response body and headers — presence, counts and lengths of well-known tags and headers. No JavaScript is executed and the page is not rendered. 3. Each category starts at 100. Every failed check subtracts a fixed deduction. Category scores are floored at 0. 4. The composite is a weighted mean of the six category scores, rounded. 5. Letter grades are assigned from fixed score bands.

Scores are pure arithmetic. A language model writes the explanatory text and the remediation advice, and is given the already-final scores with instructions that it may not change or reinterpret them. It has no path to alter a number.

2. Reproducibility

Verified: 25 real domains × 200 iterations = 5,000 scoring runs produced byte-identical output every time. Scoring is also insensitive to the key order of the input object. There is no use of the clock, randomness, locale formatting or environment state anywhere in the scoring path.

The honest caveat. That guarantee is *"same signals → same score."* It is not *"same website next week → same score,"* because the website controls what it returns. A CDN node serving a different `Cache-Control`, an A/B test, geographic routing, bot detection or personalisation can all change the signals legitimately. In practice two independent live captures of all 25 baseline domains produced identical scores — encouraging, but that is two samples, not a study.

Every scan is stored with its full result and its rubric version, so any past score can be reconstructed exactly and shown to have been computed correctly.

3. Category weights

CategoryWeight
Security26%
SEO17%
Performance16%
Mobile Usability12%
Local SEO9%
AEO8%
Accessibility8%
Best Practices4%

These weights are ActiScore's editorial judgment, not an industry standard. No standards body publishes a weighting for website quality. Security leads because ActiScore is used by managed service providers whose value to a client is security posture first. A marketing agency would reasonably weight this differently, and the weights live in one constant so they can be changed.

Before v2 the composite was an unweighted mean of six categories. That let a nearly empty page score 58 (a D) by riding a fast, unremarkable Performance score and a Best Practices score it could not fail.

4. Grade bands

GradeComposite
A93–100
B80–92
C65–79
D45–64
F0–44

These bands are arbitrary — they mirror US academic grading because it is instantly legible, not because it is derived from data.

They are also demonstrably harsh. Across 25 real sites including Stripe, GitHub, Cloudflare and the New York Times, exactly one reached an A. Stripe scores 84. This is a known open question, recorded rather than hidden.

5. The checks

Each check lists the maximum deduction and its basis:

Deduction *magnitudes* are judgment in every case, even where the check itself is a standard.

Security — 26% of composite

Scored two ways, and the report always says which. When DNS and TLS have been measured for a domain the full rubric below applies and the category is marked measured. On a cold first scan — before the background lookup has landed — only the response headers are available, the original header-only weights apply, and the category is marked inferred with a note saying so. A settled report is always measured, because the settle pass performs the lookups itself.

Full rubric (measured). Deductions total exactly 100.

CheckMax ded.BasisNotes
HTTPS18StandardScheme of the final URL after redirects
DMARC Policy16Standard — RFC 7489`p=reject` passes; `p=quarantine` −4; `p=none` −12 as monitoring, not protection; absent −16
SPF Record12Standard — RFC 7208Scored on the `all` qualifier: `-all` passes, `~all` −4, `?all`/`+all`/absent qualifier −9, no record −12
Content-Security-Policy10Standard — W3C CSPPresence only; policy strength is not assessed
Strict-Transport-Security8Standard — RFC 6797Presence only; `max-age` value not assessed
TLS Certificate8Standard — RFC 5280Expired or unreachable −8; judgment: within 21 days of expiry −5
DKIM Signing6Standard — RFC 6376Judgment: nine common selectors are probed. A miss means none of those answered, not that DKIM is absent — which is why it is weighted below SPF and DMARC
X-Frame-Options5Standard — RFC 7034Passes on `SAMEORIGIN` or `DENY`
X-Content-Type-Options5Standard — WHATWG FetchPasses when it contains `nosniff`
Software Version Disclosure5JudgmentFires when `Server` or `X-Powered-By` contains a version number
Referrer-Policy4Standard — W3CPresence only
Permissions-Policy3Standard — W3C draftPresence only

Header-only rubric (inferred). HTTPS 30, CSP 20, HSTS 15, X-Frame-Options 10, X-Content-Type-Options 8, Referrer-Policy 7, Permissions-Policy 5.

A check that could not be completed never deducts. An unreachable resolver is reported as *not checked* and scored as zero deduction — it is not evidence about the domain. This is distinguished from an authoritative "no such record", which is a real finding and is scored as one.

Every check here is a published specification, and every one is independently verifiable — `curl -I https://example.com` confirms the headers, and `dig TXT example.com` / `dig TXT _dmarc.example.com` confirm the mail records.

Limitations. These are header *presence* checks, not a security assessment. A site can score 100 here and still be vulnerable — this does not test for injection, authentication flaws, outdated software, open ports or anything requiring active probing. It is a hygiene check on what the server declares.

`X-Frame-Options` is superseded by CSP `frame-ancestors`; it is still checked because it remains widely deployed and cheap to verify.

Removed in v3: the cookie consent banner check. It was inferred from page markup, which is unreliable, and its presence is a privacy-compliance signal rather than a security control. Its weight moved onto `X-Content-Type-Options` and `Referrer-Policy`, both of which are objectively verifiable.

SEO — 20% of composite

CheckMax ded.BasisNotes
Title tag20Standard (presence) / Convention (length)Full marks at 45–65 characters
Meta description15ConventionFull marks at 120–160 characters
Single H115ConventionHTML5 permits multiple H1s in sectioning content
Canonical URL10Standard — RFC 6596Presence only
Image alt text10Standard — WCAG 1.1.1Scaled: ≤2 missing is a partial deduction
Open Graph tags5Convention — Open Graph protocol`og:title` presence
Schema markup15Standard (schema.org) / Judgment (count)Full marks at 5+ distinct types

Limitations. The character-length windows are the softest numbers in the whole rubric. Google has never published a title or description length limit; these ranges come from observed search-result truncation, which varies by device and query. A page outside the window is not penalised as failing — it takes a partial deduction.

"5 or more schema types earns full marks" is ActiScore's choice, not a schema.org requirement.

Performance — 20% of composite

As of v3 this category is measured, not inferred, whenever PageSpeed data is available. Every report states which of the two produced the score.

#### Measured path — real Core Web Vitals

Metrics come from the PageSpeed Insights API, using real Chrome user data (CrUX) where the site has enough traffic to appear in it, and a Lighthouse lab run otherwise. Thresholds are Google's published Core Web Vitals bands, not ours:

MetricGoodNeeds improvementPoorDeduction
Largest Contentful Paint≤ 2.5 s≤ 4.0 s> 4.0 s0 / 15 / 30
Cumulative Layout Shift≤ 0.1≤ 0.25> 0.250 / 10 / 20
Interaction to Next Paint≤ 200 ms≤ 500 ms> 500 ms0 / 10 / 20
Total Blocking Time≤ 200 ms≤ 600 ms> 600 ms0 / 8 / 15

This is now the most defensible category in the rubric, because the bands are not ActiScore's opinion — a prospect can check any figure in PageSpeed Insights and get the same answer.

A metric absent from the payload is skipped rather than penalised. INP has no lab equivalent, so a site with no field data would otherwise be marked down for a measurement Google could not take.

#### Inferred path — static fallback

CheckMax ded.BasisNotes
Render-blocking scripts in `<head>`30ConventionExternal scripts without `async` or `defer`
HTML document size30ConventionFull raw response size; <75 KB earns full marks
Cache-Control18Standard (header) / Judgment (scoring)Rewards `max-age`/`public`

Used when PageSpeed data is unavailable — no API key, a rate limit, a timeout, or the first-ever scan of a domain. The report labels the category "estimated from page structure" in that case, so an estimate is never presented as a measurement.

The gap between the two paths is not small and should not be assumed away. On securafy.com the static path scores Performance 100; real measurement scores it 70, because LCP is 5.0 s. That 30-point difference is why this category was rewritten.

The render-blocking script check is a genuine heuristic — it correctly ignores `async` and `defer` scripts and counts only external ones, which is the classic blocking pattern.

#### Why the first scan of a domain is usually inferred

A PSI call genuinely loads the page in Chrome and takes 20–40 seconds — far too slow to sit in front of a visitor waiting on an embedded grader. So:

refresh so the *next* scan of that domain is measured.

#### A note on measurement variance

Lighthouse lab runs are not perfectly repeatable: two runs of securafy.com minutes apart returned LCP of 5.2 s and 5.0 s. Scoring in bands rather than continuously absorbs that — both readings are "poor", so the score did not move. Metrics are also rounded before scoring, so float jitter cannot change a result. A metric sitting exactly on a band boundary can still flip between runs; that is inherent to the measurement, not to the rubric.

Mobile Usability — 15% of composite

CheckMax ded.BasisNotes
Viewport meta tag40Standard — W3CRequires `width=device-width`
Pinch-zoom not disabled30Standard — WCAG 1.4.4Disabling zoom is an accessibility failure
Responsive images30Standard — HTML `srcset`Presence of responsive image markup

Limitations. Static analysis only — the page is never rendered on a device or emulator. Tap-target sizing, font legibility and horizontal overflow are not assessed, and those are often what actually makes a site unusable on a phone.

In v2 two checks were removed from this category: Apple touch icon and theme colour. They accounted for 20 of the 100 points and neither affects whether a page works on a handset — both are homescreen and browser-chrome branding.

AEO (Answer Engine Optimisation) — 10% of composite

CheckMax ded.Basis
Structured data coverage25Judgment
FAQ content present15Judgment
Author signals10Judgment
Blog / content presence10Judgment
FAQPage or HowTo schema10Convention — schema.org types

Limitations, and this one matters for how the category is described.

This category measures structured-data readiness — whether a page carries the markup and content patterns that answer engines are known to consume. It does not measure whether the brand actually appears in AI-generated answers. No standards body defines "AEO readiness," and no published research fixes these weights.

Tools such as Profound, Peec and Otterly measure real answer-engine visibility by querying the engines. ActiScore does not do that today. Describing this category as AI-visibility measurement would be inaccurate.

*Planned:* a separate, explicitly-labelled measurement of actual answer-engine presence, kept distinct from this on-page readiness score so the two claims never blur.

Best Practices — 5% of composite

CheckMax ded.BasisNotes
Robots meta tag20Standard`noindex` is the heavy deduction
Twitter Card5ConventionPresence
Link structure5JudgmentPasses above 10 total links

Limitations. The 10-link threshold is arbitrary and this category is intentionally the lowest-weighted at 5%.

In v2, Open Graph was removed from this category — it is already scored under SEO and was therefore counted twice — and a "Forms" row was removed because it carried a zero deduction and could never fail. A row a prospect reads that cannot fail is noise.

6. Outreach threshold

A composite below 70 sets a `triggerOutreach` flag, used to mark a scanned site as worth a sales conversation.

This is a sales heuristic, not a quality judgment. It was tuned against the 25-domain baseline: the previous threshold of 80 fired on 72% of real sites including Cloudflare and Mozilla, which makes the signal useless and the sender look uninformed. At 70 it fires on 32%.

7. What ActiScore does not do

Stated plainly, because the absences matter as much as the checks:

builds its head tags client-side will score poorly on signals that are present after hydration.

probing, port scanning, vulnerability testing or credential checks.

8. Change control

The rubric is changed in place rather than versioned per tenant, because Securafy's public grader and every tenant embed share one scoring core — a fix should reach both at once.

To make that safe:

committed baseline, spanning grades A through F and including Securafy's own sites and real prospect domains.

per-category old-to-new table.

letter-grade move on a live prospect domain is flagged individually.

view refuses to silently compare scores computed under different versions.

The v1→v2 delta table is recorded in `docs/plans/2026-08-15-rubric-change-delta.txt`.

9. Open questions

Tracked honestly rather than quietly:

1. Grade A is close to unreachable — 1 of 25 real sites. The A boundary may need lowering or the deduction tables loosening. Still open. 2. Length windows for title and meta description rest on the softest evidence in the rubric and deserve a review against current search-result behaviour. 3. AEO should be renamed to reflect that it measures readiness, not visibility — pending a separate, real answer-engine visibility measurement.

Closed in v3: Performance moved from inference to measurement; the favicon check left Performance and the cookie-banner check left Security.