Skip to content

Audit · developer.mozilla.org

Dual-axis lens: Performance (Core Web Vitals, real Chrome users) + Citation-readiness (10-characteristic LLM checklist).

Axis 1 — Performance (Core Web Vitals)

Strong100%

Real Chrome user data (28-day p75). Mobile + desktop. Source: Google Chrome UX Report.

Mobile (phone)

LCPgood
1437ms
Largest Contentful Paint
INPgood
127ms
Interaction to Next Paint
CLSgood
0
Cumulative Layout Shift
FCPgood
1416ms
First Contentful Paint
TTFBgood
591ms
Time to First Byte

Desktop

LCPgood
911ms
Largest Contentful Paint
INPgood
38ms
Interaction to Next Paint
CLSgood
0.02
Cumulative Layout Shift
FCPgood
823ms
First Contentful Paint
TTFBgood
401ms
Time to First Byte

Deep dive: full developer.mozilla.org report · mobile · desktop

Axis 2 — Citation-readiness (LLM-discoverability)

Weak30%

10-characteristic checklist (Aleyda Solis). Server-rendered HTML parsed as a GPTBot/PerplexityBot would see it. HTTP 200 · 1122w body · 29ms fetch

Hard-block: recognizable, extractable, consistent, differentiated at 0.0. Without these, LLM citation is functionally impossible regardless of other scores.
AAccessible
100%
1122 words of static body content. Crawlers can extract.
BUseful
75%
Body=1122w · headings=13 · structured-data blocks=0. Heuristic for content depth + organization.
Fix: Add depth: longer body content, more H2/H3 sections, structured data blocks (Article, Dataset, DefinedTerm).
📋 Lift Useful by closing these specific gapstext
• Structured-data blocks: 0 (target ≥2 — add Article + Person OR Organization + WebPage)
FRecognizable
0%
Organization schema: ✗ · name ✗ · url ✗ · logo/image ✗ · sameAs ✗
Fix: Add Organization JSON-LD with name + url + logo + sameAs[] (≥2 public profile URLs).
📋 Paste in <head> as <script type="application/ld+json">json-ld
{
  "@context": "https://schema.org",
  "@type": "Organization",
  "@id": "https://developer.mozilla.org#org",
  "name": "Developer Mozilla",
  "alternateName": "(any old brand names, for SEO equity continuity)",
  "url": "https://developer.mozilla.org",
  "logo": "https://developer.mozilla.org/logo.png",
  "sameAs": [
    "https://twitter.com/YOUR_HANDLE",
    "https://www.linkedin.com/company/YOUR_COMPANY",
    "https://github.com/YOUR_ORG"
  ],
  "description": "(1-2 sentence elevator pitch for your brand)"
}
FExtractable
0%
0/4 H2s are quote-ready (≥25 chars, ≥5 words) · DefinedTerm ✗ · FAQ blocks=0
Fix: Rewrite H2 headings as quote-ready sentences (≥5 words, descriptive). Add DefinedTerm schema for key concepts. ≤1 FAQ block per page.
📋 Rewrite these 4 H2 heading(s) so LLM crawlers can quote them as standalone sentences (target ≥25 chars + ≥5 words)text
BEFORE:  <h2>Featured articles</h2>
AFTER:   <h2>Featured articles — [add 2-4 descriptive words so it reaches ≥5 words + ≥25 chars]</h2>

BEFORE:  <h2>Latest news</h2>
AFTER:   <h2>Latest news — [add 2-4 descriptive words so it reaches ≥5 words + ≥25 chars]</h2>

BEFORE:  <h2>Recent contributions</h2>
AFTER:   <h2>Recent contributions — [add 2-4 descriptive words so it reaches ≥5 words + ≥25 chars]</h2>

BEFORE:  <h2>Contributor Spotlight</h2>
AFTER:   <h2>Contributor Spotlight — [add 2-4 descriptive words so it reaches ≥5 words + ≥25 chars]</h2>
📋 Add DefinedTermSet schema for your key concepts (lifts Extractable +0.30)json-ld
{
  "@context": "https://schema.org",
  "@type": "DefinedTermSet",
  "@id": "https://developer.mozilla.org/#glossary",
  "name": "(your concept area) Glossary",
  "url": "https://developer.mozilla.org/glossary",
  "hasDefinedTerm": [
    {
      "@type": "DefinedTerm",
      "name": "(Term 1)",
      "description": "(1-2 sentence definition)",
      "inDefinedTermSet": "https://developer.mozilla.org/#glossary"
    },
    {
      "@type": "DefinedTerm",
      "name": "(Term 2)",
      "description": "(1-2 sentence definition)",
      "inDefinedTermSet": "https://developer.mozilla.org/#glossary"
    }
  ]
}
📋 Optional: add ONE FAQPage block per page (>1 triggers schema-spam penalty)json-ld
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "What does this site do?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "(answer in 1-3 sentences)"
      }
    },
    {
      "@type": "Question",
      "name": "How is this different from alternatives?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "(answer in 1-3 sentences)"
      }
    }
  ]
}
FConsistent
0%
No Organization.name detected — brand consistency unscorable.
Fix: Brand name should appear in <title>, nav/header, and Organization schema. Same name everywhere.
📋 Brand name in <title>, <nav>, and Organization.name must matchhtml
<!-- in <head> -->
<title>(YourBrand) · (page-specific subtitle here)</title>

<!-- in <nav> -->
<nav>
  <a href="/" class="brand">(YourBrand)</a>
  …
</nav>

<!-- in Organization JSON-LD -->
"name": "(YourBrand)"
CCorroborated
50%
36 external links · 1 to authoritative sources (.gov/.edu/wikipedia/web.dev/etc.).
Fix: Cite ≥3 authoritative sources (gov/edu/wikipedia/standards bodies/peer-reviewed). Build off-site presence (Wikipedia citation, Reddit organic, LinkedIn).
📋 Add ≥3 outbound links to authoritative sources matching your topichtml
<!-- Pick 3-5 sources relevant to your domain. Examples by topic: -->

<!-- Web performance / dev -->
<a href="https://web.dev/articles/vitals">web.dev Core Web Vitals</a>
<a href="https://developer.mozilla.org/en-US/docs/Web/Performance">MDN Web Performance</a>
<a href="https://developer.chrome.com/docs/crux/">Chrome UX Report</a>

<!-- Schema / standards -->
<a href="https://schema.org/Organization">schema.org reference</a>
<a href="https://w3.org/TR/">W3C specifications</a>

<!-- Health / science -->
<a href="https://www.nih.gov/health-information">NIH Health Info</a>
<a href="https://www.cdc.gov/">CDC</a>
<a href="https://pubmed.ncbi.nlm.nih.gov/">PubMed</a>

<!-- Finance / business -->
<a href="https://www.sec.gov/edgar.shtml">SEC EDGAR</a>
<a href="https://www.federalreserve.gov/">Federal Reserve</a>
FCredible
20%
Person schema ✗ · sameAs=0 · /about or /methodology link=✓ · datePublished=✗ · dateModified=✗
Fix: Add Person schema with sameAs[] (≥2 profiles). Link /about + /methodology in nav/footer. Add datePublished + dateModified to Article schema.
📋 Add Person schema (operator/author identity)json-ld
{
  "@context": "https://schema.org",
  "@type": "Person",
  "@id": "https://developer.mozilla.org/about#author",
  "name": "(your full name — operator or primary author)",
  "jobTitle": "Founder",
  "url": "https://developer.mozilla.org/about",
  "sameAs": [
    "https://twitter.com/YOUR_HANDLE",
    "https://www.linkedin.com/in/YOUR_HANDLE",
    "https://github.com/YOUR_HANDLE"
  ],
  "worksFor": {
    "@id": "https://developer.mozilla.org#org"
  }
}
📋 Add datePublished + dateModified to your Article/WebPage schemajson-ld
"datePublished": "2026-01-15",
"dateModified": "2026-08-12"
FDifferentiated
0%
0 POV markers detected (e.g. "our view", "we found", "we recommend").
Fix: Add explicit POV sentences ("Our view: …", "We measured …", "We recommend …"). LLMs cite pages with stance more than encyclopedic neutrality.
📋 Add explicit POV sentences in the body text (LLMs cite pages with stance more than neutral encyclopedic content)markdown
> Our view: (your specific stance on the topic this page covers)

> We measured (a number you actually measured) and found (insight).

> We recommend (specific action) because (reason backed by your data).
DFresh
30%
dateModified ≤90d (schema)=✗ · Last-Modified header ≤90d=✓ · visible "updated YYYY" text=✗
Fix: Add dateModified to schema; serve Last-Modified header; render visible "Last verified YYYY-MM-DD" near content.
📋 Add visible "Last verified" stamp near contenthtml
<p class="text-xs text-gray-500">
  Last verified <time datetime="2026-08-12">2026-08-12</time>
</p>
📋 Add datePublished + dateModified to Article/WebPage schemajson-ld
{
  "@type": "WebPage",
  "datePublished": "2026-01-15",
  "dateModified": "2026-08-12"
}
📋 Set HTTP Last-Modified response header (web framework-specific)text
# Express / Node:
res.setHeader('Last-Modified', new Date().toUTCString());

# Next.js middleware (middleware.ts):
import { NextResponse } from 'next/server';
export function middleware() {
  const res = NextResponse.next();
  res.headers.set('Last-Modified', new Date().toUTCString());
  return res;
}
DTransactable
25%
2 affordance keywords · mailto=✗ · contact/pricing/signup link=✗
Fix: Make the citation actionable: clear CTA, contact page, pricing, or mailto. Visitors who arrive from an LLM citation should be able to act.
📋 Add a visible mailto contact (LLM citation arrivals need somewhere to act)html
<a href="mailto:contact@developer.mozilla.org">contact@developer.mozilla.org</a>
📋 Add a /contact or /pricing page link from your footer/navhtml
<footer>
  …
  <a href="/contact">Contact</a>
  <a href="/pricing">Pricing</a>
</footer>

Prioritized fixes with copy-paste code

Ordered by impact across both axes. Top 6. Click the snippet rows to expand the exact code to copy.

  1. high[extractable] Rewrite H2 headings as quote-ready sentences (≥5 words, descriptive). Add DefinedTerm schema for key concepts. ≤1 FAQ block per page.
    Lifts Extractable from 0.00 → 1.00 (gap 1.00).
    📋 Rewrite these 4 H2 heading(s) so LLM crawlers can quote them as standalone sentences (target ≥25 chars + ≥5 words)text
    BEFORE:  <h2>Featured articles</h2>
    AFTER:   <h2>Featured articles — [add 2-4 descriptive words so it reaches ≥5 words + ≥25 chars]</h2>
    
    BEFORE:  <h2>Latest news</h2>
    AFTER:   <h2>Latest news — [add 2-4 descriptive words so it reaches ≥5 words + ≥25 chars]</h2>
    
    BEFORE:  <h2>Recent contributions</h2>
    AFTER:   <h2>Recent contributions — [add 2-4 descriptive words so it reaches ≥5 words + ≥25 chars]</h2>
    
    BEFORE:  <h2>Contributor Spotlight</h2>
    AFTER:   <h2>Contributor Spotlight — [add 2-4 descriptive words so it reaches ≥5 words + ≥25 chars]</h2>
    📋 Add DefinedTermSet schema for your key concepts (lifts Extractable +0.30)json-ld
    {
      "@context": "https://schema.org",
      "@type": "DefinedTermSet",
      "@id": "https://developer.mozilla.org/#glossary",
      "name": "(your concept area) Glossary",
      "url": "https://developer.mozilla.org/glossary",
      "hasDefinedTerm": [
        {
          "@type": "DefinedTerm",
          "name": "(Term 1)",
          "description": "(1-2 sentence definition)",
          "inDefinedTermSet": "https://developer.mozilla.org/#glossary"
        },
        {
          "@type": "DefinedTerm",
          "name": "(Term 2)",
          "description": "(1-2 sentence definition)",
          "inDefinedTermSet": "https://developer.mozilla.org/#glossary"
        }
      ]
    }
    📋 Optional: add ONE FAQPage block per page (>1 triggers schema-spam penalty)json-ld
    {
      "@context": "https://schema.org",
      "@type": "FAQPage",
      "mainEntity": [
        {
          "@type": "Question",
          "name": "What does this site do?",
          "acceptedAnswer": {
            "@type": "Answer",
            "text": "(answer in 1-3 sentences)"
          }
        },
        {
          "@type": "Question",
          "name": "How is this different from alternatives?",
          "acceptedAnswer": {
            "@type": "Answer",
            "text": "(answer in 1-3 sentences)"
          }
        }
      ]
    }
  2. high[recognizable] Add Organization JSON-LD with name + url + logo + sameAs[] (≥2 public profile URLs).
    Lifts Recognizable from 0.00 → 1.00 (gap 1.00).
    📋 Paste in <head> as <script type="application/ld+json">json-ld
    {
      "@context": "https://schema.org",
      "@type": "Organization",
      "@id": "https://developer.mozilla.org#org",
      "name": "Developer Mozilla",
      "alternateName": "(any old brand names, for SEO equity continuity)",
      "url": "https://developer.mozilla.org",
      "logo": "https://developer.mozilla.org/logo.png",
      "sameAs": [
        "https://twitter.com/YOUR_HANDLE",
        "https://www.linkedin.com/company/YOUR_COMPANY",
        "https://github.com/YOUR_ORG"
      ],
      "description": "(1-2 sentence elevator pitch for your brand)"
    }
  3. medium[credible] Add Person schema with sameAs[] (≥2 profiles). Link /about + /methodology in nav/footer. Add datePublished + dateModified to Article schema.
    Lifts Credible from 0.20 → 1.00 (gap 0.80).
    📋 Add Person schema (operator/author identity)json-ld
    {
      "@context": "https://schema.org",
      "@type": "Person",
      "@id": "https://developer.mozilla.org/about#author",
      "name": "(your full name — operator or primary author)",
      "jobTitle": "Founder",
      "url": "https://developer.mozilla.org/about",
      "sameAs": [
        "https://twitter.com/YOUR_HANDLE",
        "https://www.linkedin.com/in/YOUR_HANDLE",
        "https://github.com/YOUR_HANDLE"
      ],
      "worksFor": {
        "@id": "https://developer.mozilla.org#org"
      }
    }
    📋 Add datePublished + dateModified to your Article/WebPage schemajson-ld
    "datePublished": "2026-01-15",
    "dateModified": "2026-08-12"
  4. medium[consistent] Brand name should appear in <title>, nav/header, and Organization schema. Same name everywhere.
    Lifts Consistent from 0.00 → 1.00 (gap 1.00).
    📋 Brand name in <title>, <nav>, and Organization.name must matchhtml
    <!-- in <head> -->
    <title>(YourBrand) · (page-specific subtitle here)</title>
    
    <!-- in <nav> -->
    <nav>
      <a href="/" class="brand">(YourBrand)</a>
      …
    </nav>
    
    <!-- in Organization JSON-LD -->
    "name": "(YourBrand)"
  5. medium[differentiated] Add explicit POV sentences ("Our view: …", "We measured …", "We recommend …"). LLMs cite pages with stance more than encyclopedic neutrality.
    Lifts Differentiated from 0.00 → 1.00 (gap 1.00).
    📋 Add explicit POV sentences in the body text (LLMs cite pages with stance more than neutral encyclopedic content)markdown
    > Our view: (your specific stance on the topic this page covers)
    
    > We measured (a number you actually measured) and found (insight).
    
    > We recommend (specific action) because (reason backed by your data).
  6. medium[fresh] Add dateModified to schema; serve Last-Modified header; render visible "Last verified YYYY-MM-DD" near content.
    Lifts Fresh from 0.30 → 1.00 (gap 0.70).
    📋 Add visible "Last verified" stamp near contenthtml
    <p class="text-xs text-gray-500">
      Last verified <time datetime="2026-08-12">2026-08-12</time>
    </p>
    📋 Add datePublished + dateModified to Article/WebPage schemajson-ld
    {
      "@type": "WebPage",
      "datePublished": "2026-01-15",
      "dateModified": "2026-08-12"
    }
    📋 Set HTTP Last-Modified response header (web framework-specific)text
    # Express / Node:
    res.setHeader('Last-Modified', new Date().toUTCString());
    
    # Next.js middleware (middleware.ts):
    import { NextResponse } from 'next/server';
    export function middleware() {
      const res = NextResponse.next();
      res.headers.set('Last-Modified', new Date().toUTCString());
      return res;
    }
Saved URLs live in your browser; come back any time and re-audit with one click. View watchlist →

Share or embed

Free to embed. The widget links back to vitalslens.com so we can keep the audit free.

Embed snippet
<iframe src="https://webvitalstool.com/embed/audit?url=developer.mozilla.org" width="100%" height="640" frameborder="0" loading="lazy" title="VitalsLens audit · developer.mozilla.org"></iframe>

Want fleet monitoring across multiple URLs? VitalsLens Pro — €19/mo.