Auditing

plimo.ai

  1. Search
  2. AI visibility
  3. Backlinks
  4. Security
  5. Compliance
  6. Does it work
  7. Speed & visual

Check 7 of 7

Speed & visual

Diffing against baseline

https://plimo.airun urierb

Audit report

Plimo

plimo.ai

AI image and video generator with trending templates

Derived from your page
86/100Ready to be seen7 failing · 31 to review

Last scanned Oct 28, 2026

Launching

Is this your product?

Sign in to see its launch and what you can add to it.

Executive summary

163checks run
7issues
81locked
Search: 100 out of 100100AI visibility: 87 out of 10087Backlinks: not measured—Security: 78 out of 10078Compliance: 49 out of 10049Does it work: 100 out of 100100Speed & visual: 86 out of 1008686/ 100
  • 49ComplianceConsent, policy pages, and the disclosures you owe.
  • 78SecurityHeaders, TLS, and what an attacker sees first.
  • 86Speed & visualHow fast it loads and how it renders at every size.
  • 87AI visibilityWhether answer engines cite you when they should.
  • 100SearchWhether search engines can find, read and rank the page.
  • 100Does it workLinks, forms and flows that fail silently.
  • —BacklinksWho links to you, and whether those links carry weight.

What to fix

Ordered by what it costs you, not by which check found it.

In order of what it costs you

  1. 01SecurityNo clickjacking protection (frame-ancestors / X-Frame-Options)Leaves the site open to attack, or gets it flagged as unsafe in browsers.Add `Content-Security-Policy: frame-ancestors 'none'` (or 'self'), and for legacy browsers also send `X-Frame-Options: DENY`.
  2. 02SecurityHTTP Strict Transport Security (HSTS) not enforcedLeaves the site open to attack, or gets it flagged as unsafe in browsers.Return `Strict-Transport-Security: max-age=63072000; includeSubDomains` on every HTTPS response so browsers pin the origin to HTTPS for two years.
  3. 03SecurityNo Content-Security-PolicyLeaves the site open to attack, or gets it flagged as unsafe in browsers.Start with a report-only policy, then enforce e.g.
  4. 04SecurityDMARC policy at the domain apexLeaves the site open to attack, or gets it flagged as unsafe in browsers.After a monitoring window at p=none with rua= collecting reports, raise to p=quarantine then p=reject once all legitimate senders align.
  5. 05SecuritySPF record and default qualifierLeaves the site open to attack, or gets it flagged as unsafe in browsers.Tighten the trailing qualifier to -all once every legitimate sending source is enumerated in the record.
  6. 06SecurityThird-party scripts lack Subresource IntegrityLeaves the site open to attack, or gets it flagged as unsafe in browsers.Add an SRI hash and crossorigin to each pinned third-party script: `<script src=...
  7. 07Speed & visualText compression and static-asset cachingA slow or broken render makes visitors bounce, and Google ranks it lower.Enable Brotli (fallback Gzip) at the CDN/server for all text MIME types, and set Cache-Control: public, max-age=31536000, immutable on content-hashed static…
  8. 08Speed & visualImage weight and modern formats (AVIF/WebP)A slow or broken render makes visitors bounce, and Google ranks it lower.Convert to AVIF with WebP fallback via <picture>, generate responsive srcset widths, and strip metadata.
  9. 09Speed & visualLab performance score (weighted)A slow or broken render makes visitors bounce, and Google ranks it lower.Prioritize by weight: TBT and LCP together are 55% of the score, so shipping the hydration-bundle and LCP-image fixes above moves the number most.
  10. 10Speed & visualThird-party script impactA slow or broken render makes visitors bounce, and Google ranks it lower.Load third parties with async/defer after the main content, lazy-init the chat widget on interaction, use a facade for embeds, and add preconnect/dns-prefetc…

+ 17 more below, itemised by area.

What we saw

Agentic Browsing · can an AI agent use this site

A Lighthouse factor since May 2026: whether an autonomous agent (ChatGPT agent mode, Claude computer-use) can reach the page, read what it is, and complete a task.

2/ 3
AccessReady

The agent's fetcher can reach the page and gets real content, not a challenge or a blank shell.

5 signals · scored 100

ComprehensionDegraded

The page is structured so the agent can read what it is: labels, semantics, language and schema.

7 signals · scored 97

OperabilityReady

The agent can actually act: controls are wired and keyboard-operable, with no overlay trapping it.

4 signals · scored 100

8720 of 13 graded

AI visibility

Whether answer engines cite you when they should.

The score grades whether an answer engine can fetch your pages and whether it finds enough on them to cite you.

1 of 20 measured failing

  • Needs work

    No /llms.txt curated map for LLM agents (advisory, not a ranking factor)

    Measured
    no usable /llms.txt (HTTP 404)
    Threshold
    WARN only, never fail. Google (Illyes, Jul 2025; Mueller: 'no AI system currently uses llms.txt') consumes nothing from it, and an analysis of 137k sites found 97% of published llms.txt files were never requested. Perplexity/Claude/coding agents (Cursor, Copilot) do retrieve it, so it is a low-cost nicety, not a defect.
    Observed
    Fix
    Optional: publish a Markdown /llms.txt (H1 site name, blockquote summary, H2 sections of curated links) if you serve docs/agent audiences. Do not prioritize this over robots.txt, SSR, or schema, since nothing consumes it for search ranking.
    Search Engine Roundtable: Google says no AI system currently uses llms.txt
  • Needs work

    No Wikipedia or Wikidata entity for the brand

    Measured
    no Wikipedia/Wikidata entity linked for "Plimo"
    Threshold
    Warn on absence for an early-stage brand; the signal is weighted heavily because Wikipedia and Wikidata are among the most-referenced sources in LLM training and retrieval, and they anchor the entity an engine attributes facts to. Notability rules mean many small brands cannot get a page, so this is a signal, not an obligation.
    Observed
    Fix
    Where the brand meets notability, pursue a Wikipedia article and a Wikidata item, and link both from Organization sameAs. Where it does not, strengthen the other entity anchors (Crunchbase, LinkedIn, G2) that engines fall back to.
    Semrush: why AI cites third-party sources
  • 10 checks passedShow them
    • Passing

      no retrieval bot explicitly Disallowed

      Bar met
      Any Disallow that matches OAI-SearchBot, Claude-SearchBot, or PerplexityBot on citation-eligible paths is a fail. OpenAI states sites opted out of OAI-SearchBot 'will not be shown in ChatGPT search answers.'
      Observed
      OpenAI: Bots & crawler docs (OAI-SearchBot opt-out removes ChatGPT search visibility)
    • Passing

      no retrieval bot caught by a wildcard block

      Bar met
      Retrieval bots must resolve to Allow. A wildcard or 'block all AI' rule that also matches OAI-SearchBot / Claude-SearchBot / PerplexityBot is a fail; robots.txt is longest-match/most-specific per agent, so a specific Allow is required to override `*`.
      Observed
      Search Engine Land: Anthropic's three-bot framework (blocking training bot does not block search/user bots, and vice-versa)
    • Passing

      bot UA → HTTP 200, no challenge

      Bar met
      Fail if any retrieval bot UA (OAI-SearchBot, PerplexityBot, Claude-User/Claude-SearchBot) receives a non-2xx or a challenge page. WAF/firewall rules run before robots.txt, so a WAF block overrides a robots.txt Allow. Bot Fight Mode and 'block AI bots' managed rules commonly false-positive here.
      Observed
      Cloudflare docs: Block AI bots (WAF rules run before robots.txt; challenges can hit legitimate search bots)
    • Passing

      ChatGPT-User and Claude-User both get a 2xx with real HTML (baseline 200)

      Bar met
      The ChatGPT-User and Claude-User user-agents must each receive a 2xx with real, non-trivial HTML content, with no WAF/CAPTCHA/JS-challenge interstitial and not a blank client-side-rendered shell. These are the on-demand agent fetchers ChatGPT agent mode and Claude computer-use send when a user asks them to complete a task on a live site (distinct from the retrieval/index bots OAI-SearchBot / PerplexityBot). If either UA is blocked or served nothing, an autonomous agent cannot read or act on the page.
      Observed
      OpenAI: Bots & crawler docs (ChatGPT-User is the on-demand agent fetcher for ChatGPT agent/user actions, distinct from OAI-SearchBot)
    • Passing

      1 JSON-LD block(s) parse cleanly

      Bar met
      Fail on any JSON that does not parse or references an invalid @type/required-property violation. Broken JSON-LD is equivalent to no structured data. The parser drops the whole block, not just the bad field.
      Observed
      schema.org: Organization type reference
    • Passing

      0 of 20 sampled URLs broken (0.0%)

      Bar met
      Warn above ~5% broken-link ratio. Vercel measured ChatGPT wasting 34.82% and Claude 34.16% of fetches on 404s vs Googlebot's 8.22%. AI crawlers have far weaker URL-validation, so dead links disproportionately consume their limited budget and starve real pages.
      Observed
      Vercel: The rise of the AI crawler (ChatGPT 34.82% / Claude 34.16% of fetches were 404s vs Googlebot 8.22%)
    • Passing

      0 of 15 internal links redirect

      Bar met
      Warn if internal links depend on redirects (any chain > 1 hop is worse). Vercel measured ChatGPT spending an extra 14.36% of fetches following redirects vs Googlebot's 1.49%. Non-rendering bots waste budget and sometimes drop chained targets.
      Observed
      Vercel: The rise of the AI crawler (ChatGPT +14.36% fetches on redirects vs Googlebot 1.49%)
    • Passing

      462 of 462 <url> entries carry <lastmod>

      Bar met
      Warn when no sitemap is discoverable via robots.txt/root, or when <lastmod> is absent/static. lastmod is the primary machine signal telling AI crawlers which pages changed and when. Without it they re-crawl blindly and miss updates on their limited budget.
      Observed
      Foglift: Content freshness in AI search (sitemap lastmod signals what changed)
    • Passing

      missing URL correctly returns HTTP 404

      Bar met
      Warn on any soft 404 (200 status on a not-found page). Non-rendering AI crawlers rely on status codes to decide what to store; a 200 on an error page gets ingested as real content and can surface as a garbage citation, while also masking the broken-link waste in aeo-404-crawl-waste.
      Observed
      SearchOptimo: Do AI crawlers render JavaScript (bots depend on initial HTML + status codes)
    • Passing

      no AI bots blocked; retrieval bots allowed

      Bar met
      Legitimate configuration, so this passes. Blocking GPTBot/ClaudeBot only affects model-training corpus, not live citations. Training accounted for ~7-8x search-crawl volume in 2025, so this is a common and valid data-rights choice.
      Observed
      Cloudflare Radar 2025 Year in Review: training vs search vs user-action crawl breakdown
7825 of 29 graded

Security

Headers, TLS, and what an attacker sees first.

The score grades your certificate and the headers your server sends back.

4 of 25 measured failing

  • Failing

    HTTP Strict Transport Security (HSTS) not enforced

    Measured
    No Strict-Transport-Security header on the HTTPS response.
    Threshold
    Header must be present with max-age >= 15768000 (6 months). Observatory: hsts-not-implemented = -20; max-age under 6 months (hsts-implemented-max-age-less-than-six-months) = -10; OWASP recommends max-age=63072000; includeSubDomains.
    Observed
    Fix
    Return `Strict-Transport-Security: max-age=63072000; includeSubDomains` on every HTTPS response so browsers pin the origin to HTTPS for two years.
    Mozilla HTTP Observatory scoring: HSTS
  • Failing

    No Content-Security-Policy

    Measured
    No Content-Security-Policy header on the primary HTML document.
    Threshold
    A CSP must be present. Observatory: csp-not-implemented = -25; a strong policy (csp-implemented-with-no-unsafe-default-src-none) earns +10.
    Observed
    Fix
    Start with a report-only policy, then enforce e.g. `default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; upgrade-insecure-requests`.
    MDN: Content-Security-Policy
  • Failing

    No clickjacking protection (frame-ancestors / X-Frame-Options)

    Measured
    Neither X-Frame-Options nor a CSP frame-ancestors directive is present — the page can be framed by any origin.
    Threshold
    Set X-Frame-Options: DENY|SAMEORIGIN or CSP frame-ancestors. Observatory: x-frame-options-not-implemented = -20; frame-ancestors via CSP (x-frame-options-implemented-via-csp) = +5.
    Observed
    Fix
    Add `Content-Security-Policy: frame-ancestors 'none'` (or 'self'), and for legacy browsers also send `X-Frame-Options: DENY`.
    OWASP Secure Headers Project
  • Failing

    MIME sniffing disabled (X-Content-Type-Options)

    Measured
    No X-Content-Type-Options header — browsers may MIME-sniff responses.
    Threshold
    Header value must be exactly `nosniff`. Observatory: x-content-type-options-not-implemented = -5; nosniff = 0 (clean).
    Observed
    Fix
    None needed. Ensure the header is also emitted on static asset and API responses, not only HTML.
    MDN: X-Content-Type-Options
  • Needs work

    HSTS present but not preload-eligible

    Measured
    plimo.ai is not preload-eligible: its HTTPS response sends no Strict-Transport-Security header.
    Threshold
    Preload list requires max-age >= 31536000 (1 year), includeSubDomains, and the preload token, plus an HTTP->HTTPS redirect on the same host. Observatory awards hsts-preloaded = +5.
    Observed
    Fix
    Raise max-age to 31536000+, add the `preload` token (`max-age=63072000; includeSubDomains; preload`), then submit the apex domain at hstspreload.org.
    hstspreload.org submission requirements
  • Needs work

    Referrer-Policy not set to a privacy-preserving value

    Measured
    No Referrer-Policy header — the browser default applies rather than an explicit private policy.
    Threshold
    Send a private policy such as no-referrer or strict-origin-when-cross-origin. Observatory: referrer-policy-private = +5; referrer-policy-unsafe (e.g. unsafe-url) = -5.
    Observed
    Fix
    Add `Referrer-Policy: strict-origin-when-cross-origin` (or `no-referrer` for maximum privacy).
    MDN: Referrer-Policy
  • Needs work

    No Permissions-Policy restricting powerful features

    Measured
    No Permissions-Policy header — camera, microphone, geolocation and payment are allowed by default.
    Threshold
    Explicitly deny unused features. OWASP recommends locking each feature to () or (self), e.g. camera=(), microphone=(), geolocation=(), payment=(). (Not scored by Observatory; OWASP best practice.)
    Observed
    Fix
    Emit a deny-by-default policy, e.g. `Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=()`, enabling only what the app uses.
    OWASP Secure Headers Project: Permissions-Policy
  • Needs work

    Third-party scripts lack Subresource Integrity

    Measured
    25 of 25 cross-origin script(s) load without a Subresource Integrity hash.
    Threshold
    Cross-origin scripts should carry integrity + crossorigin. Observatory: sri-not-implemented-but-external-scripts-loaded-securely = -5; worst case (loaded over http without SRI) = -50.
    Observed
    Fix
    Add an SRI hash and crossorigin to each pinned third-party script: `<script src=... integrity="sha384-..." crossorigin="anonymous">`. Only feasible for version-pinned assets.
    Mozilla HTTP Observatory scoring: SRI
  • Needs work

    security.txt disclosure-contact file

    Measured
    No security.txt at /.well-known/security.txt or the legacy /security.txt path.
    Threshold
    A security.txt SHOULD be served at exactly /.well-known/security.txt over HTTPS as text/plain, and MUST contain Contact and Expires fields per RFC 9116. Missing it is a minor readiness gap (a finder has no defined channel), not a vulnerability.
    Observed
    Fix
    Publish /.well-known/security.txt with at least `Contact: mailto:security@example.com` and a future-dated `Expires:` in RFC 3339 form. Serve it as text/plain; charset=utf-8 over HTTPS.
    RFC 9116 (security.txt), §3 location & §2.5 required fields
  • Needs work

    SPF record and default qualifier

    Measured
    A single SPF record is published but ends in ~all (softfail) rather than -all.
    Threshold
    Exactly one SPF TXT record MUST exist (multiple = permerror). It should end in -all (fail) for a domain whose sender set is known; ~all (softfail) is tolerated during rollout. +all (pass-all) is a fail: it authorizes the entire internet.
    Observed
    Fix
    Tighten the trailing qualifier to -all once every legitimate sending source is enumerated in the record. Keep total DNS lookups under the RFC 7208 limit of 10 to avoid permerror.
    RFC 7208 (SPF), §5.1 the "all" mechanism
  • Needs work

    DMARC policy at the domain apex

    Measured
    DMARC exists but publishes p=none — monitor-only, blocking no spoofed mail.
    Threshold
    A DMARC record MUST exist and reach enforcement (p=quarantine or p=reject) with an rua= aggregate-report address. p=none is monitor-only and blocks nothing; it is a valid starting point but not a passing end state.
    Observed
    Fix
    After a monitoring window at p=none with rua= collecting reports, raise to p=quarantine then p=reject once all legitimate senders align. Always publish rua=mailto:dmarc@example.com so failures are visible.
    RFC 7489 (DMARC), §6.3 record format & policy
  • Needs work

    CAA records restricting certificate issuance

    Measured
    No CAA record at the apex — any public CA may issue a certificate for the domain.
    Threshold
    A CAA record SHOULD exist naming the authorized CA(s). With no CAA record, any public CA may issue for the domain, widening the mis-issuance surface. Its absence is a hardening gap, not an active exposure.
    Observed
    Fix
    Publish CAA pinning your issuer, e.g. `example.com. CAA 0 issue "letsencrypt.org"` plus an `iodef` mailto for violation reports. Add issuewild to control wildcard issuance.
    RFC 8659 (DNS CAA Resource Record)
  • Needs work

    DNSSEC signing of the zone

    Measured
    The zone is unsigned — no DNSKEY records and the resolver did not set the Authenticated Data flag.
    Threshold
    DNSSEC SHOULD be enabled (a DS record at the parent, RRSIG/DNSKEY in the zone) so DNS answers, including the MX, TXT and CAA records the other checks rely on, cannot be forged in transit. Unsigned is common but leaves those records spoofable.
    Observed
    Fix
    Enable DNSSEC at your DNS provider and publish the resulting DS record through your registrar. Confirm the chain of trust validates end to end before relying on it.
    RFC 9364 / BCP 237: DNSSEC (best current practice)
  • 12 checks passed and 3 had nothing to gradeShow them
    • Passing

      No Access-Control-Allow-Origin header on the document response (no wildcard exposure).

      Bar met
      Do not expose authenticated data with a wildcard ACAO. Observatory: cross-origin-resource-sharing-implemented-with-universal-access = -50. A wildcard combined with Allow-Credentials: true is rejected by browsers and is a red flag.
      Observed
      MDN: CORS / Access-Control-Allow-Origin
    • Passing

      No precise server/framework version strings are exposed in response headers.

      Bar met
      Response headers SHOULD NOT leak precise version strings (Server, X-Powered-By, X-AspNet-Version). A version banner lets an attacker map known CVEs directly to the host. Disclosure is a warn: it eases reconnaissance rather than being an exploit itself.
      Observed
      OWASP WSTG-INFO-02: Fingerprint Web Server
    • Passing

      No http:// subresources referenced in the pre-JS HTML.

      Bar met
      No http:// subresources on an https:// page. Observatory penalises insecure schemes in CSP passive content (csp-implemented-with-insecure-scheme-in-passive-content-only = -10; active = -20).
      Observed
      MDN: Mixed content
    • Passing

      No same-origin JS bundles were referenced to probe for source maps.

      Bar met
      Production source maps SHOULD NOT be publicly served: they reconstruct original, un-minified source (including comments and internal paths), enlarging the attacker's view of client logic. A reachable .map is a warn, not a breach.
      Observed
      OWASP WSTG-CONF-04: Old Backup & Unreferenced Files
    • Passing

      /.git/HEAD is not served (HTTP 404).

      Bar met
      /.git/ MUST NOT be reachable over HTTP. A served .git lets an unauthenticated visitor reconstruct full source, commit history and any secrets ever committed. Any 200 (vs 403/404) on /.git/HEAD or /.git/config is a fail.
      Observed
      OWASP WSTG-CONF-04: Old Backup & Unreferenced Files
    • Passing

      /.env is not served (HTTP 404).

      Bar met
      /.env and sibling config files (.env.local, config.php.bak, wp-config.php~) MUST return 403/404, never 200. A served .env typically exposes database URLs, API keys and secret tokens. Any 200 with dotenv-shaped content is a fail.
      Observed
      OWASP WSTG-CONF-04: Old Backup & Unreferenced Files
    • Passing

      No conventional phpinfo page, database dump or archive was reachable.

      Bar met
      Reachable database dumps or archives are a fail; a live phpinfo() page is at least a warn: it discloses full environment, loaded modules, paths and env vars, aiding targeted attack. Conventional names MUST return 404/403.
      Observed
      OWASP WSTG-CONF-04: Old Backup & Unreferenced Files
    • Passing

      No conventional admin/debug endpoint answered with unauthenticated internals.

      Bar met
      Conventional admin/debug surfaces (/actuator/health, /actuator/env, /debug, /server-status, /admin, /wp-admin exposed to the world) SHOULD require auth or return 403/404 unauthenticated. An open actuator/env or server-status leaking internals is a warn escalating toward fail if secrets are shown.
      Observed
      OWASP WSTG-CONF-05: Enumerate Admin Interfaces
    • Passing

      Port-80 request returns 301 to the identical HTTPS host before serving content.

      Bar met
      First hop from http:// must be a redirect to https:// on the same host. Observatory: redirection-missing = -20, redirection-not-to-https = -20, redirection-off-host-from-http = -5; redirection-to-https = 0 (clean).
      Observed
      Mozilla HTTP Observatory scoring: Redirection
    • Passing

      The connection negotiated TLSv1.3; TLS 1.2 is the floor and 1.3 is preferred.

      Bar met
      TLS 1.0 and TLS 1.1 MUST NOT be used (RFC 8996); serve TLS 1.2 as the floor, TLS 1.3 preferred.
      Observed
      RFC 8996: Deprecating TLS 1.0 and TLS 1.1
    • Passing

      The certificate is within its validity window (expires Jan 11 13:16:06 2027 GMT, ~75 days).

      Bar met
      Certificate must be trusted, hostname-matching, unexpired, and chain-complete (no missing intermediates). Observatory flags hsts-invalid-cert / redirection-invalid-cert = -20 when the chain fails.
      Observed
      Mozilla HTTP Observatory scoring: TLS/cert
    • Passing

      No dangling CNAME to an unclaimed third-party resource was found among the apex, www and document host.

      Bar met
      No subdomain CNAME MUST point to a deprovisioned third-party resource (GitHub Pages, S3, Heroku, Fastly, Netlify) that an attacker could re-register. A dangling CNAME whose target returns a provider 'no such site' fingerprint is a fail.
      Observed
      OWASP WSTG-CONF-10: Test for Subdomain Takeover
    • Measured, nothing to grade

      CSP weakened by 'unsafe-inline' / 'unsafe-eval'

      Why grey
      No enforced CSP is present; unsafe-inline/eval weakening only applies once a policy exists.
      Threshold
      script-src must not contain 'unsafe-inline' or 'unsafe-eval'. Observatory: csp-implemented-with-unsafe-inline = -20, csp-implemented-with-unsafe-eval = -10; a nonce/hash-based policy with no unsafe = +5.
      Fix
      Replace 'unsafe-inline' with per-request nonces or hashes (`script-src 'self' 'nonce-<rand>'`); style-src 'unsafe-inline' alone is tolerated but still worth removing.
      Mozilla HTTP Observatory scoring: CSP
    • Measured, nothing to grade

      Session cookie missing Secure / HttpOnly / SameSite

      Why grey
      The homepage set no cookies; session cookies issued on authenticated routes are not observable from a URL alone.
      Threshold
      Session cookies must carry Secure, HttpOnly, and SameSite=Lax|Strict. Observatory: cookies-session-without-secure-flag = -40, cookies-session-without-httponly-flag = -30, cookies-anticsrf-without-samesite-flag = -20; fully hardened = +5.
      Fix
      Add Secure (HTTPS-only), HttpOnly (no JS access), and SameSite=Lax (or Strict) to every session/auth cookie.
      Mozilla HTTP Observatory scoring: Cookies
    • Measured, nothing to grade

      DKIM public key discoverable at a conventional selector

      Why grey
      DKIM selectors are arbitrary and provider-specific; a custom selector cannot be discovered from a URL alone, so absence is not provable.
      Threshold
      A mail-sending domain SHOULD publish a DKIM public key (v=DKIM1; p=…) reachable at its provider's selector, so DMARC has a second aligned authentication method beyond SPF. Absence cannot be proven passively (selectors are arbitrary), so this is advisory, not a hard fail.
      Fix
      Enable DKIM signing at your ESP and confirm the published key resolves at the selector your provider uses. Verify DMARC alignment so the signing domain matches the From: domain.
      RFC 6376 (DKIM), §3.6.1 key record
4919 of 30 graded

Compliance

Consent, policy pages, and the disclosures you owe.

The score grades your consent flow and the policy pages you owe your visitors.

1 of 19 measured failing

  • Needs work

    Missing 'Do Not Sell or Share My Personal Information' link

    Measured
    1 advertising host(s) present, no opt-out link
    Threshold
    A business that sells or shares personal information must provide a clear and conspicuous opt-out link, titled 'Do Not Sell or Share My Personal Information' or offer the 'Your Privacy Choices' control (CCPA/CPRA). Binding within California; applicability depends on the business meeting CCPA thresholds and on it 'selling/sharing', jurisdiction- and status-scoped.
    Observed
    Fix
    If CCPA applies and cross-context advertising is used, add a conspicuous 'Do Not Sell or Share My Personal Information' (or 'Your Privacy Choices') link that opts the user out, and honour it alongside GPC.
    California Attorney General: CCPA (opt-out of sale/sharing requirements)
  • Needs work

    No easy, persistent way to withdraw consent

    Measured
    no persistent consent-settings control found
    Threshold
    Withdrawing consent must be as easy as giving it, and possible at any time (GDPR Art. 7(3), binding). Regulators expect a persistent, always-reachable mechanism (e.g. a footer 'Cookie settings' link or floating icon). The persistence expectation is EDPB/CNIL guidance layered on the binding withdrawal right.
    Observed
    Fix
    Add an always-available control (footer 'Cookie settings' link or floating icon) that reopens the preferences panel, letting users withdraw with effort no greater than the original acceptance.
    EDPB Report of the Cookie Banner Taskforce (17 Jan 2023), §7 (withdrawal of consent)
  • Needs work

    Accessibility statement (European Accessibility Act)

    Measured
    no accessibility statement found
    Threshold
    Directive (EU) 2019/882 (EAA) applies from 28 June 2025 to consumer-facing products/services including e-commerce, banking, e-books, and transport ticketing. In-scope services must meet the accessibility requirements and provide information on how the service meets them (an accessibility statement). Microenterprises providing services (<10 staff AND ≤€2m turnover/balance sheet) are exempt for services. The statement's presence is the signal; national transposing law governs enforcement.
    Observed
    Fix
    If in scope and not a microenterprise, publish an accessibility statement describing how the service meets the EAA requirements (typically via EN 301 549 / WCAG 2.1 AA). Confirm scope and the microenterprise carve-out manually. Turnover/headcount are not detectable from the site.
    Directive (EU) 2019/882 EAA (binding, applies 28 Jun 2025)
  • Needs work

    Security / breach reporting contact disclosure

    Measured
    no security contact disclosure
    Threshold
    GDPR imposes a binding breach-notification duty on the controller (Art. 33-34) but does not require a public breach contact on the website. A published, machine-findable security contact is BEST PRACTICE per RFC 9116 (security.txt), which is an informational standard, not law. The detectable signal is a security.txt or a named security/privacy contact.
    Observed
    Fix
    Publish /.well-known/security.txt with a 'Contact:' field and add a privacy/DPO contact to satisfy the separate Art. 13 DPO-contact requirement. Distinguish clearly: security.txt is voluntary guidance; the Art. 13 DPO contact (where a DPO exists) is binding.
    RFC 9116 security.txt (guidance, not law)
  • Needs work

    Data-subject-rights request route & stated response timeframe

    Measured
    no usable rights-request route
    Threshold
    Art. 12(2) requires the controller to 'facilitate the exercise' of data-subject rights, and Art. 12(3) sets a binding deadline: respond without undue delay and at the latest within one month of receipt (extendable by two further months for complex requests, with notice). A published, usable request route and, as good practice, a stated timeframe are the visible signals.
    Observed
    Fix
    Provide a specific channel (privacy@ address or a form) for rights requests and state the one-month statutory response window. The one-month deadline is binding regardless of whether it is published; publishing it is the detectable signal.
    GDPR Art. 12(2)-(3) (binding) + EDPB SME rights guidance
  • Needs work

    Article 13 mandatory disclosure elements

    Measured
    7/8 Art. 13 topics present; missing 1
    Threshold
    Art. 13(1)-(2) enumerates a closed list that must ALL appear: controller identity + contact, DPO contact (where applicable), purposes AND legal basis, legitimate interests (if that basis is used), recipients/categories, transfer information, retention period, the data-subject rights, right to withdraw consent, right to complain to a supervisory authority, and whether provision is a statutory/contractual requirement.
    Observed
    Fix
    Add the four missing elements. This is a SIGNAL check: presence of a heading does not prove the content is adequate; a lawyer should confirm substance. A scanner can only flag that the required topics are textually absent.
    GDPR Art. 13(1)-(2) (binding) + EDPB transparency guidance
  • 9 checks passed and 5 had nothing to gradeShow them
    • Passing

      a privacy policy resolves (200)

      Bar met
      Any site collecting personal data (contact forms, analytics, account signup, server logs of IP addresses) must provide the Article 13 information at the point of collection. The information must actually be published and reachable, not merely drafted. A URL is the only signal a scanner can see.
      Observed
      GDPR Art. 13 (information at point of collection)
    • Passing

      terms document linked and reachable

      Bar met
      Unlike the privacy notice, there is no single EU statute mandating a published ToS for every site, but for any paid or contractual service the pre-contract information duties of the Consumer Rights Directive (2011/83/EU) and e-Commerce Directive Art. 10 make published terms effectively necessary. Presence of a linked, reachable terms document is the signal; adequacy is not machine-checkable.
      Observed
      e-Commerce Directive Art. 10 / Consumer Rights Directive (context)
    • Passing

      a linked page names who runs the site

      Bar met
      Art. 5(1) of Directive 2000/31/EC requires every commercial online service to render 'easily, directly and permanently accessible' at minimum: the provider's name, geographic address of establishment, email, and, where registered, trade-register and VAT identifiers. The CJEU (C-298/07) held email alone is insufficient; a second rapid, direct contact channel is required.
      Observed
      e-Commerce Directive 2000/31/EC Art. 5 (binding)
    • Passing

      transfer mechanism disclosed (2 US recipient(s))

      Bar met
      Art. 13(1)(f) requires stating that a transfer to a third country occurs and 'the existence or absence of an adequacy decision' or the appropriate safeguards (Chapter V). Post-Schrems II, US transfers rely on the recipient's EU-US Data Privacy Framework self-certification OR on SCCs plus a transfer impact assessment. The scanner can only detect that a US recipient exists and that no transfer basis is disclosed.
      Observed
      GDPR Art. 44-46 (binding) + EU-US Data Privacy Framework
    • Passing

      children's data is addressed

      Bar met
      Art. 8 GDPR: where an information-society service is offered directly to a child on the basis of consent, processing is lawful only for a child of at least 16 (Member States may lower this to 13), and below that age parental consent is required. This check only applies where the service targets or foreseeably reaches minors and relies on consent: it is conditional, not universal.
      Observed
      GDPR Art. 8 (child's consent, binding; national age varies)
    • Passing

      page language declared: lang="en"

      Bar met
      WCAG 2.2 Success Criterion 3.1.1 Language of Page (Level A): the default human language of each page must be programmatically determinable via a valid lang attribute on <html>. This is fully machine-detectable and one of the highest-confidence automated checks.
      Observed
      WCAG 2.2 SC 3.1.1 (W3C Recommendation)
    • Passing

      all 10 images carry an alt attribute

      Bar met
      WCAG 2.2 SC 1.1.1 Non-text Content (Level A): all non-text content needs a text alternative that serves the equivalent purpose; purely decorative images need alt="" (empty, but present). A scanner reliably detects MISSING alt attributes; it CANNOT judge whether present alt text is meaningful. That requires human review.
      Observed
      WCAG 2.2 SC 1.1.1 (W3C Recommendation)
    • Passing

      all 2 form controls are programmatically labelled

      Bar met
      WCAG 2.2 SC 3.3.2 Labels or Instructions (Level A) and SC 4.1.2 Name, Role, Value (Level A): every form control must have a programmatically associated, persistent label. Placeholder text is not a label (it vanishes on input). Missing programmatic labels are machine-detectable; whether an existing label is clear is not.
      Observed
      WCAG 2.2 SC 3.3.2 / 4.1.2 (W3C Recommendation)
    • Passing

      heading order intact and links have discernible names

      Bar met
      WCAG 2.2 SC 1.3.1 Info and Relationships (Level A) requires a programmatically correct heading hierarchy; SC 2.4.4 Link Purpose (In Context) (Level A) and SC 4.1.2 require each link to have a discernible, purposeful accessible name. Skipped heading levels and empty/duplicate link names are machine-detectable; whether headings are logically ordered in MEANING is a manual judgement.
      Observed
      WCAG 2.2 SC 1.3.1 & 2.4.4 (W3C Recommendation)
    • Measured, nothing to grade

      No 'Reject all' control on the banner's first layer

      Why grey
      This can't be determined from a URL alone.
      Threshold
      If 'Accept all' is present on a given layer, a same-layer 'Reject all' should be present. The EDPB Cookie Banner Taskforce records this as the majority DPA position; it is a supervisory-authority interpretation, not settled across all authorities, so it is a strong recommendation rather than uniform binding law.
      Fix
      Add a 'Reject all' button on the first layer, functionally equivalent to and no more effortful than 'Accept all'. One click to refuse should mirror one click to accept.
      EDPB Report of the Cookie Banner Taskforce (adopted 17 Jan 2023), §2
    • Measured, nothing to grade

      Tracking cookies mislabelled as 'strictly necessary'

      Why grey
      This can't be determined from a URL alone.
      Threshold
      The strictly-necessary exemption to consent (Art. 5(3)) covers only storage 'strictly necessary' to provide a service explicitly requested by the user. Analytics and advertising identifiers do not qualify and cannot be classified as essential. Binding law; the EDPB Taskforce lists 'essential' misclassification as a common infringement.
      Fix
      Reclassify analytics and advertising cookies into consent-gated Analytics/Marketing categories. Reserve 'strictly necessary' for session, security, load-balancing, and explicit user-requested functionality.
      EDPB Report of the Cookie Banner Taskforce (17 Jan 2023), §5 (essential cookie classification)
    • Measured, nothing to grade

      Banner omits cookie duration and third-party recipients

      Why grey
      This can't be determined from a URL alone.
      Threshold
      Users must be told, before consenting, the duration of the operation of cookies and whether third parties may have access to them (CJEU Planet49, binding). Absence of this information undermines informed consent.
      Fix
      Disclose, at the point of consent, each cookie's retention duration and the third parties (or vendor categories) that can access the stored information, e.g. via an accessible cookie table or vendor list.
      CJEU, Planet49, Case C-673/17 (1 Oct 2019): duration & third-party access must be disclosed
    • Measured, nothing to grade

      Consent / re-prompt lifetime exceeds 13 months

      Why grey
      We read this one and there was nothing on your site to grade.
      Threshold
      Consent should be refreshed at a reasonable interval; CNIL recommends the consent record not exceed 13 months and identifiers no more than ~13 months. This is a French supervisory-authority recommendation (jurisdiction-specific), not an EU-wide statutory maximum. Treat as a warn, not a hard fail.
      Fix
      Cap the consent-record lifetime at 13 months and re-prompt on expiry. Applies where French/CNIL exposure is relevant; elsewhere confirm the local authority's interval.
      CNIL: Cookies and other trackers: guidance & recommendations (13-month consent interval)
    • Measured, nothing to grade

      WCAG 1.4.3 Contrast (Minimum)

      Why grey
      This can't be determined from a URL alone.
      Threshold
      WCAG 2.2 SC 1.4.3 Contrast (Minimum) (Level AA): normal text must reach a 4.5:1 contrast ratio against its background; large text (≥18pt, or ≥14pt bold) must reach 3:1. Contrast is computable from colour values, but overlaps, gradients, images-behind-text, and opacity can defeat static analysis. Those cases need manual verification.
      Fix
      Darken muted text to at least #767B80 on white and adjust button/background pairs to reach 4.5:1 (3:1 for large text). Manually verify text set over images or gradients.
      WCAG 2.2 SC 1.4.3 (W3C Recommendation)
10021 of 27 graded

Does it work

Links, forms and flows that fail silently.

The score grades the links and forms we could open and submit.

21 checks, none failing

  • 12 checks passed and 4 had nothing to gradeShow them
    • Passing

      0 of 15 sampled internal links return 4xx

      Bar met
      Zero linked 4xx URLs. Google removes previously-indexed URLs that return any 4xx (except 429) from the index and treats the content as non-existent, so every internal link to a 4xx wastes crawl and leaks link equity.
      Observed
      Google Search Central: How HTTP status codes affect Google Search (4xx)
    • Passing

      0 of 14 checked URLs return 5xx

      Bar met
      Zero 5xx on crawlable URLs. Googlebot slows crawling on 5xx and, if the errors persist, drops the affected URLs from the index; crawl rate only recovers once the server returns 2xx again.
      Observed
      Google Search Central: How HTTP status codes affect Google Search (5xx)
    • Passing

      no redirect loop in 15 sampled chains

      Bar met
      Zero loops. A URL that eventually redirects back to itself never resolves; Googlebot abandons it after 10 hops and the page becomes uncrawlable and unindexable.
      Observed
      Google Search Central: Redirects (crawlers stop after 10 hops)
    • Passing

      no active http:// subresources

      Bar met
      Zero active (blockable) mixed content. On an HTTPS page, browsers hard-block active http:// resources (scripts, stylesheets, iframes, XHR/fetch) because they can rewrite the whole page. Blocked scripts/CSS break functionality outright.
      Observed
      MDN: Mixed content (blockable vs upgradable)
    • Passing

      15 critical subresources all load (200, CORS ok)

      Bar met
      Every referenced script, stylesheet, and font must return 200 with correct CORS. A 4xx on a stylesheet or a CORS-blocked font degrades or breaks the rendered page, and Google may classify the resulting broken render as a soft 404.
      Observed
      Google Search Central: Soft 404s from unloaded resources
    • Passing

      15 assets served with correct MIME types

      Bar met
      Scripts must be served with a JavaScript MIME type and stylesheets with text/css. With X-Content-Type-Options: nosniff (increasingly default behaviour), a script sent as text/plain or a CSS file sent as text/html is blocked outright.
      Observed
      MDN: X-Content-Type-Options: nosniff (script/style blocking)
    • Passing

      longest chain 0 hop(s)

      Bar met
      Keep redirects to a single hop. Google's crawlers follow up to 10 redirect hops and then give up, treating the URL as an error; every extra hop also adds latency and dilutes the signal. Anything over 3 hops is a warning, over 10 a hard failure.
      Observed
      Google Search Central: Redirects, crawlers follow up to 10 hops
    • Passing

      directives agree with the served response

      Bar met
      Directives must agree with reality. A canonical pointing at a non-200 URL, a self-referencing canonical on a page that 301s elsewhere, or 'index' + 'noindex' both present are self-contradictions Google resolves unpredictably. ~0.7% of pages in the 2025 Web Almanac show a canonical mismatch.
      Observed
      HTTP Archive: 2025 Web Almanac, SEO chapter (canonicals)
    • Passing

      no combinatorial parameter pattern in homepage links

      Bar met
      URL parameters must not multiply into a near-infinite crawl space. Faceted navigation, sort/filter params, session IDs, and calendar 'next month' links generate effectively unbounded duplicate URLs that exhaust crawl budget on low-value pages.
      Observed
      Google Search Central: Faceted navigation & infinite spaces
    • Passing

      15 sampled sitemap URLs all return 200

      Bar met
      Sitemap URLs should return 200, be canonical, not noindex, and not be robots-blocked. A single sitemap file is capped at 50,000 URLs and 50MB uncompressed. Past that, Google ignores the overflow or rejects the file.
      Observed
      Google Search Central: Build and submit a sitemap (limits & URL rules)
    • Passing

      15 of 15 internal request(s) responded without error

      Bar met
      Keep server response time low and consistent; web.dev rates TTFB good at <=800ms, poor above 1,800ms. Network timeouts and connection resets are treated by Googlebot like 5xx server errors and quickly suppress the URL in Search.
      Observed
      web.dev: Time to First Byte (TTFB) thresholds
    • Passing

      HTTP/3 advertised via Alt-Svc

      Bar met
      Serve at least HTTP/2, which multiplexes requests over one connection and removes head-of-line blocking. In the 2024 Web Almanac ~70-71% of sites use HTTP/2; HTTP/3 is a bonus (leading CDNs reach ~69% adoption vs <5% of origins).
      Observed
      HTTP Archive: 2024 Web Almanac, HTTP chapter (protocol adoption)
    • Measured, nothing to grade

      Form cannot submit: no action, no handler, no endpoint

      Why grey
      We read this one and there was nothing on your site to grade.
      Threshold
      Every form must have a working submission path: a resolvable action endpoint or a bound submit handler, and a control whose type actually submits. A form that silently discards input is a dead conversion surface.
      Fix
      Add a valid action + method or a bound onSubmit that POSTs to a real endpoint and calls preventDefault; make the trigger <button type="submit"> (that is the default, but broken wrappers override it). Confirm the handler is attached post-hydration.
      MDN: <input type="submit"> (default submit behavior & the action target)
    • Measured, nothing to grade

      Form endpoint errors on valid, well-formed input

      Why grey
      We read this one and there was nothing on your site to grade.
      Threshold
      A non-transactional form given valid input must reach a success state, not a server error. Unexpected post-submit failures are a top driver of form/checkout abandonment.
      Fix
      Fix the endpoint's 500 (validate/log server-side), return a 2xx with a confirmation the UI can render, and show an explicit error message on failure instead of silently resetting. NEVER exercise this on transactional/account-creating forms.
      Baymard: Usability Testing of Inline Form Validation (post-submit errors drive abandonment)
    • Measured, nothing to grade

      Site search or filter returns nothing / errors on valid queries

      Why grey
      We read this one and there was nothing on your site to grade.
      Threshold
      Search and filter controls must return correct, non-empty results for queries that should match, without console errors. A broken search/filter silently strands users on discovery paths.
      Fix
      Fix the search endpoint's 500 and ensure filter changes actually trigger a re-fetch/re-render (bind the change handler post-hydration). Verify a known-match query returns the expected items.
      MDN: Window: error event (surfacing runtime failures on feature paths)
    • Measured, nothing to grade

      Valid input rejected, and no inline validation before submit

      Why grey
      We read this one and there was nothing on your site to grade.
      Threshold
      Well-formed input must be accepted, and forms should validate inline (on blur) so errors surface before submission. 31% of sites lack inline validation; unexpected post-submit errors are a documented abandonment driver.
      Fix
      Replace the broken regex with permissive email validation (or rely on type="email" + server check), and add on-blur inline validation that clears once corrected, so users are not stopped by a surprise error at submit.
      Baymard: Usability Testing of Inline Form Validation (31% lack it; validate on blur)
8622 of 29 graded

Speed & visual

How fast it loads and how it renders at every size.

The score is Google's performance number for your mobile page, plus how your layout holds at every screen size.

1 of 22 measured failing

PageSpeed · Lighthouse categories & Core Web Vitals

Mobile · ranked

86
Performance
100
Accessibility
100
Best Practices
100
SEO
2.1 sFCP (lab) · lab
3.5 sSpeed Index · lab
3.5 sLCP (lab) · lab
170 msTBT · lab
0CLS (lab) · lab

Load sequence

Mobile · ranked at 375ms
0.4s
Mobile · ranked at 750ms
0.8s
Mobile · ranked at 1125ms
1.1s
Mobile · ranked at 1500ms
1.5s
Mobile · ranked at 1875ms
1.9s
Mobile · ranked at 2250ms
2.3s
Mobile · ranked at 2625ms
2.6s
Mobile · ranked at 3000ms
3.0s

Desktop

89
Performance
100
Accessibility
100
Best Practices
100
SEO
0.5 sFCP (lab) · lab
1.0 sSpeed Index · lab
2.1 sLCP (lab) · lab
90 msTBT · lab
0.051CLS (lab) · lab

Load sequence

Desktop at 375ms
0.4s
Desktop at 750ms
0.8s
Desktop at 1125ms
1.1s
Desktop at 1500ms
1.5s
Desktop at 1875ms
1.9s
Desktop at 2250ms
2.3s
Desktop at 2625ms
2.6s
Desktop at 3000ms
3.0s
  • Needs work · mobile, ranked

    Unused JavaScript shipped to the client

    Measured
    Est savings of 179 KiB
    Threshold
    The lab audit flags a script only when more than 20 KiB of it is unused (Lighthouse's UNUSED_BYTES_IGNORE_THRESHOLD = 20 * 1024). Target: ship only what the route needs.
    Observed
    Fix
    Code-split by route, dynamic-import below-the-fold and interaction-only components, tree-shake dead exports, and lazy-load third-party SDKs after load. Verify with the DevTools Coverage tab.
    DesktopEst savings of 155 KiB
    Lab audit: Reduce unused JavaScript
  • Needs work · mobile, ranked

    Field-data availability (field vs lab coverage)

    Measured
    No CrUX field data (mobile) — Core Web Vitals here are lab (Lighthouse) estimates only
    Threshold
    Field data only reports a URL/origin once it has sufficient real-user samples over the 28-day window. Low-traffic pages fall back to origin-level data or have none at all.
    Observed
    Fix
    Treat field data as the source of truth for pass/fail and the lab audit as the diagnostic for why. Where no field data exists, label results 'lab estimate' and instrument a RUM/web-vitals beacon to build first-party field data.
    DesktopNo CrUX field data (desktop) — Core Web Vitals here are lab (Lighthouse) estimates only
    Field data (real-user)
  • Needs work · mobile, ranked

    Lab performance score (weighted)

    Measured
    Performance = 86 / 100 (Lighthouse mobile)
    Threshold
    0 to 49 poor (red) · 50 to 89 needs improvement (orange) · 90 to 100 good (green). Weighted average: TBT 30% · LCP 25% · CLS 25% · FCP 10% · Speed Index 10%.
    Observed
    Fix
    Prioritize by weight: TBT and LCP together are 55% of the score, so shipping the hydration-bundle and LCP-image fixes above moves the number most. CLS is already green and contributes little upside.
    DesktopPerformance = 89 / 100 (Lighthouse desktop)
    Lab audit: Performance scoring
  • Needs work · mobile, ranked

    Image weight and modern formats (AVIF/WebP)

    Measured
    Est savings of 555 KiB
    Threshold
    The lab audit flags legacy JPEG/PNG that would be meaningfully smaller as AVIF or WebP. Target: AVIF/WebP with correctly-sized, compressed variants.
    Observed
    Fix
    Convert to AVIF with WebP fallback via <picture>, generate responsive srcset widths, and strip metadata. Route images through an image CDN / the framework image component so format and size are negotiated per request.
    DesktopEst savings of 1,114 KiB
    Web Almanac 2025: Performance (image formats)
  • Needs work

    Text compression and static-asset caching

    Measured
    text compression: on; cache policy: 4 asset(s) with a short TTL
    Threshold
    The lab audit expects Gzip/Brotli on text responses; 'Serve static assets with an efficient cache policy' expects hashed static assets to use a long TTL (≥ ~1 year, immutable).
    Observed
    Fix
    Enable Brotli (fallback Gzip) at the CDN/server for all text MIME types, and set Cache-Control: public, max-age=31536000, immutable on content-hashed static assets while keeping HTML short-lived.
    Lab audit: Enable text compression
  • Needs work · mobile, ranked

    Third-party script impact

    Measured
    3 third parties use 274 ms of the main thread
    Threshold
    The lab audit flags third-party main-thread blocking time (guideline: keep well under ~250 ms). No hard pass/fail; higher blocking is worse.
    Observed
    Fix
    Load third parties with async/defer after the main content, lazy-init the chat widget on interaction, use a facade for embeds, and add preconnect/dns-prefetch for the ones that must load early. Drop anything not earning its cost.
    Desktop3 third parties use 223 ms of the main thread
    Lab audit: Reduce the impact of third-party code
  • 3 checks passed and 5 had nothing to gradeShow them
    • Passing · mobile, ranked

      Time to first byte 32 ms (3%) · Element render delay 985 ms (97%)

      Bar met
      Guideline split of the LCP time: TTFB ~40% and resource load duration ~40%, with load delay + render delay together under ~20% (render delay ~10%). Load delay should be near-zero.
      Observed
      DesktopTime to first byte 23 ms (1%) · Resource load delay 1.1 s (69%) · Resource load duration 62 ms (4%) · Element render delay 413 ms (26%)
      web.dev: Optimize LCP (sub-parts)
    • Passing · mobile, ranked

      No LCP image on this page. The largest element is not an image.

      Bar met
      The LCP image must be eagerly loaded and, ideally, high-priority. Never apply loading="lazy" to the LCP/above-the-fold image.
      Observed
      DesktopLCP image carries loading="lazy"
      web.dev: The performance effects of too much lazy loading
    • Passing · mobile, ranked

      Main-thread work = 2.0 s (Lighthouse mobile)

      Bar met
      The lab audit warns as main-thread time climbs (guideline: keep total under ~2 s and individual tasks under 50 ms). Long tasks (> 50 ms) block input.
      Observed
      DesktopMain-thread work = 1.4 s (Lighthouse desktop)
      Lab audit: Minimize main-thread work
    • Measured, nothing to grade

      Largest Contentful Paint (field, p75)

      Why grey
      No field data yet: not enough real-user traffic to report page-speed history.
      Threshold
      Good ≤ 2.5 s · Needs improvement 2.5 to 4.0 s · Poor > 4.0 s, evaluated at the 75th percentile of real-user page loads
      Fix
      Preload the LCP image with fetchpriority="high", drop it from any lazy-loading, and serve a correctly-sized AVIF/WebP. Cut the render-blocking chain ahead of it so the browser discovers the image sooner.
      web.dev: Largest Contentful Paint (LCP)
    • Measured, nothing to grade

      First Contentful Paint (field, p75)

      Why grey
      No field data yet: not enough real-user traffic to report page-speed history.
      Threshold
      Good ≤ 1.8 s · Needs improvement 1.8 to 3.0 s · Poor > 3.0 s at p75. Field and lab metric; not a Core Web Vital.
      Fix
      The same two fixes move FCP: cut TTFB (caching/CDN) and clear render-blocking CSS/JS. FCP improvement usually pulls LCP down with it since they share the early critical path.
      web.dev: First Contentful Paint (FCP)
    • Measured, nothing to grade

      Cumulative Layout Shift (field, p75)

      Why grey
      No field data yet: not enough real-user traffic to report page-speed history.
      Threshold
      Good ≤ 0.10 · Needs improvement 0.10 to 0.25 · Poor > 0.25 at p75. CLS is unitless (a layout-shift score, not a time).
      Fix
      Already within budget. Hold the line by setting width/height (or aspect-ratio) on all media, reserving space for embeds/ads, and using font-display: optional or size-adjust to neutralize the font swap.
      web.dev: Cumulative Layout Shift (CLS)
    • Measured, nothing to grade

      Interaction to Next Paint (field, p75)

      Why grey
      No field data yet: not enough real-user traffic to report page-speed history.
      Threshold
      Good ≤ 200 ms · Needs improvement 200 to 500 ms · Poor > 500 ms at p75. INP replaced FID as a Core Web Vital in March 2024.
      Fix
      Break up the long input handler (yield with scheduler.yield or setTimeout), defer non-critical work off the interaction path, and shrink hydration cost. Use the TBT lab proxy (speed-tbt-lab) to catch regressions between field readings.
      web.dev: Interaction to Next Paint (INP)
    • Measured, nothing to grade

      Time to First Byte (field, p75)

      Why grey
      No field data yet: not enough real-user traffic to report page-speed history.
      Threshold
      Good ≤ 0.8 s · Needs improvement 0.8 to 1.8 s · Poor > 1.8 s at p75. TTFB is a diagnostic (not itself a Core Web Vital) and available as both field and lab.
      Fix
      Add full-page or edge caching / CDN in front of the origin, cache expensive DB queries, and stream the HTML (early flush) so bytes leave the server before the full page is assembled.
      web.dev: Time to First Byte (TTFB)

Unlock the full audit

What to do next.

The report above is yours, free and complete. The full audit opens the deeper checks; the rest are the things worth doing once you have read it.

The full audit

You have seen the free scan.

Now open every check.

$19one-time

checks run134
issues7
locked81

The deeper checks, each with its evidence and its fix: how AI answer engines read you, who links to you, and how the page really renders.

Watch

$29/mo

Keep the audit running on a schedule and get an alert the moment a check slips: security headers, speed, broken forms, a lost backlink.

Review article

$59

Your own indexed page, written by us from your site. It ranks for a name-plus-review search, carries 3 links back to you, and is built to be cited when someone asks an AI what to use.

Premium launch

$29

Your day, your listing written, no badge on your site.

Featured

$19-79 for 30 days

A Spotlight card beside every browse page and guide, or a slide in the homepage carousel, for 30 days. Labelled as paid, with its views and clicks counted while it runs.

SEO / GEO / backlink boost

From $299

Done-for-you off-page work: guest placements, structured-data fixes, and answer-engine optimisation so you show up in Google and in the AI answers that quote their sources.

The listing

In the directory

It launched today and the listing is public.

On these numbers

Core Web Vitals come from field data at the 75th percentile. They describe your users, not a lab. Backlink and answer-engine figures depend on paid data sources and show as grey until those are connected. A grey check means we could not read it, not that it failed.

Send me this report

One email with what we found on plimo.ai, and one note three days later if nobody has claimed it. Nothing after that.

Newsletter

What launched, every Monday

Every Monday: what launched on LaunchScaler that week, what is launching next, and the reviews we published. Confirm your email once and you're in.