Brandfine Docs
Concepts

SEO Audit

One-click multi-category audit — SEO, Performance, GEO/AIO, CMS health — covering every URL in your sitemap.

Every Brandfine workspace gets a built-in SEO audit alongside its analytics. One click runs ~35 checks across four categories, samples your sitemap for lab + field performance via Google PageSpeed Insights, parses each post's rendered HTML, and surfaces a grouped list of issues with fix suggestions.

The audit is designed to be useful for any site shape — whether your posts live in Brandfine, in static markdown files, or aren't posts at all (landing-page-only sites). URL discovery comes from your /sitemap.xml, not from assumptions about your URL structure.

What you see in the CMS

Sidebar → Growth → SEO & Analytics → click any workspace → SEO audit tab. The page has:

  • Four score cards (SEO / Performance / GEO/AIO / CMS health) — 0-100, color-coded green/amber/rose.
  • Coverage panel — sitemap source, URL groups detected, Lighthouse sample list, PSI/CrUX coverage, page-HTML reachability.
  • Issues lists — grouped by severity (Critical / Warnings / Info), each grouped by check id with a [template] badge when many posts share the same root cause.
  • "Copy summary" — one click → a Markdown summary of the whole audit on your clipboard, ready to paste into Slack or a chat with support.

Audit runs are backgrounded — clicking Run audit returns immediately; the UI polls and updates when the run completes (~60-120s typical). Page reloads + tab switches survive the run.

The four score categories

CategoryWhat it coversSource
SEOTitle, meta description, canonical, h1, lang, hreflang, OG completeness, JSON-LD validity, robots-meta, alt textMix of CMS-DB checks + Lighthouse SEO audits (via PSI) + HTML DOM parsing
PerformanceLCP, CLS, TBT, FCP, modern image formats (lab) + LCP, CLS, INP (real-user CrUX field data when available)Google PageSpeed Insights — same engine + scoring that web.dev / Search Console use
GEO / AIOAI-search readiness: AI-crawler robots.txt allow-list, /llms.txt presence + format, first-paragraph relevance, content freshness, structured blocks, internal links, author byline, data densityCustom checks designed for the AI-citation era
CMS healthWorkspace config: domain set, schema.org populated, sitemap reachable + covers published posts, post slug uniqueness, translation-orphan detectionDB-side checks against your workspace state

Performance is special. It's the median across sampled URLs of Lighthouse's published performance score — the same number you'd see if you pasted your URL into PageSpeed Insights. The other categories use Brandfine's own scoring formula because they're built from custom checks Google's Lighthouse doesn't run.

When PSI returns no data (network blip, key not configured), Performance renders as instead of a misleading 100. Re-run to retry — the PsiClient does a single automatic retry on transient failures already.

How URL discovery works

Brandfine never asks you to declare URL patterns. The audit reads your /robots.txt, follows the Sitemap: declarations there, and recurses one level into <sitemapindex> if present. Sitemap entries

  • their <xhtml:link rel="alternate" hreflang> siblings flatten into a single URL list, capped at 1000 URLs per run.

If robots.txt doesn't declare sitemaps (or doesn't exist), the audit falls back to probing /sitemap.xml and /sitemap-index.xml at conventional paths. If nothing's reachable, it audits the homepage only and flags cms:workspace:sitemap-present as a critical issue (no sitemap = real SEO problem worth surfacing).

URL groups — template-aware sampling

The audit clusters discovered URLs by shared path prefix: 56 URLs under /en/services/ become one group, 23 under /blog/ become another. Groups ≥ 3 URLs. The coverage panel surfaces detected groups so customers can see their site's structure as the audit sees it:

Detected 5 URL groups from the sitemap:
  /en/services/  × 54
  /services/     × 54
  /en/           × 7
  /en/legal/     × 4
  /legal/        × 4

Lighthouse sampling uses these groups: the audit picks one URL per group instead of just the first N from the sitemap. That way a performance regression on the blog template gets caught, even when /blog/* URLs appear deep in the sitemap.

URL ↔ Post matching

For workspaces that publish posts through Brandfine, the audit matches each sitemap URL to a cms Post by slug + locale. Matched posts attach to per-URL check context, so post-specific checks (translation-orphan, freshness, author-byline) can run. Unmatched URLs — landing pages, doc pages, category indexes, or sites that use Brandfine for analytics only — still get audited for SEO / perf / GEO / DOM checks; they just skip post-specific concerns.

Reading the issues list

Each issue is rendered as a row:

  • [critical/fail] badge — severity + status (warn = amber, fail = rose, pass = green).
  • × N posts count — how many URLs hit this check.
  • [template] badge (violet) — when ≥3 URLs share the IDENTICAL observed value, the audit recognises this as a single template- level finding ("fix once, all instances disappear") rather than N separate problems.
  • Fix suggestion — actionable copy where the audit can offer one. Some checks just surface the observation.
  • Affected posts list (expandable) — for non-template-level findings with multiple instances, click "Show affected posts" to see the URL + Edit link per affected post.

Severity bands

SeverityWhen to fireScore impact (per failure, max)
criticalReal defect — page not indexable, missing required tag, no sitemap100 × weight
warningReal concern — short content, missing OG image, slug-naming issue30 × weight
infoOptimization suggestion — title length tuning, byline absence, data-density5 × weight

warn status (vs fail) halves the penalty — used when something is present but suboptimal (e.g. meta description present but only 58 chars).

The "Copy summary" button

Audits surface a lot of detail. The Markdown export packs the whole report — scores, coverage, every finding with observed values + fix suggestions — into a paste-friendly format suitable for sharing in chat (with support, with an AI assistant, with your team). Click Copy summary, paste anywhere.

Example output:

# SEO Audit
Status: completed · Finished: 2026-05-31T21:48:36.918Z
URLs audited: 136 (sitemap source: sitemap-index)
Cms posts in workspace: 110

## Scores
- SEO: 92/100
- Performance: 87/100 (Lighthouse via PSI)
- GEO/AIO: 96/100
- CMS Health: 100/100

## Lighthouse sample (5 pages)
- https://example.com/
- https://example.com/en/services/uk-eta/
- ...

## Critical (1)
- **perf:lcp** [warn/critical] × 5
  Fix: LCP measures when the largest content element renders. …
  Variants: 5

What gets sent to Google

The Performance score (and CrUX field data) come from Google PageSpeed Insights. Each call sends the audited URL to Google's infrastructure. The same URL Google already crawls for ranking — there's no new data-sharing surface introduced — but if your workspace audits URLs you'd rather Google not know about (private staging, draft preview routes), leave GOOGLE_PSI_API_KEY unset. The audit still runs; all perf:* and crux:* checks skip cleanly with a clear "PSI not configured" message.

PSI free tier is 25,000 calls/day per project; each audit makes ~5 calls (one per sampled URL), so a daily-cron-across-every- workspace scenario still has years of headroom before the quota matters.

When the audit can't see your site

Audits run from Brandfine's infrastructure → your site over the public internet. If your site requires auth, blocks unknown user-agents at the CDN, or returns 4xx/5xx for the bot UA BrandfineAuditBot/1.0, the audit will surface that as low "Page HTML" coverage in the coverage panel (rendered in rose when less than 50% of URLs return parseable HTML). Whitelist the User-Agent on your CDN's bot-management rules if you intentionally want Brandfine's audit to succeed.

The PSI leg runs from Google's infrastructure separately, so a Google-allowed-but-Brandfine-blocked CDN config produces partial audits (PSI metrics work, DOM checks skip). The coverage panel distinguishes these.

Run audits manually when:

  • You ship a redesign or template change
  • You publish a batch of new content (sitemap + cms drift detection catches "published in cms but not yet redeployed")
  • You see a SERP-impressions drop in Search Console

For workspaces under active development, weekly is plenty — nothing in the audit looks at "what changed since last run" yet. Scheduled audits + trend charts are a planned future enhancement.

On this page