SEO Audit — Christchurch Miami

First automated probe pass · delta from 2026-05-09 manual audit
2026-05-14 Composite: 29 / 100 · Online: 2 / 5

Executive summary What changed since the 2026-05-09 manual audit — surfaced by automated probe at tools/seo_dashboard/probe.py

Composite dropped 72 → 29 (formula change + 3 surfaces offline). The two numbers are not directly comparable — 72 was Jeff's manual qualitative score across the 5/9 narrative audit; 29 is the first formula-based composite from automated probes. Going forward, every daily run uses the same formula, so 29 is the baseline future passes are measured against. The drop reflects two real facts: (1) the formula counts subdomains that don't resolve as 0, and (2) three CCM subdomains that the 5/9 audit treated as live now return NXDOMAIN.
Composite
29
Formula-computed across 5 tracked CCM surfaces. Each surface scored 0–100 (see methodology below), averaged.
Surfaces online
2 / 5
christchurchmiami.org + resources.christchurchmiami.org respond. es.cm, prayer.cm, app.cm return NXDOMAIN.
CCM main score
85
christchurchmiami.org alone scores 85 — strong canonical, 17 JSON-LD types, 84 sitemap URLs, robots.txt + hreflang declared.
Critical open
4
3 new DNS findings + 1 carried-over Ad Grant blocker (/en-espanol 404).
🚨 Hreflang reciprocity is broken on the main site. christchurchmiami.org declares <link rel="alternate" hreflang="es" href="https://es.christchurchmiami.org/"> in its HTML head — but es.christchurchmiami.org returns NXDOMAIN. Google can interpret a broken hreflang pair as a configuration error and drop the en page from the cluster, or treat both as misconfigured. This is the top action item for this pass.

What changed since 2026-05-09

Surface2026-05-09 state2026-05-14 stateΔ
christchurchmiami.org Snappages main site, 11 critical/high findings, 6 medium Snappages main site, 200 OK, 53.8 KB body, 17 JSON-LD types, 84 sitemap URLs, hreflang declared (en/es/x-default) stable
es.christchurchmiami.org Not tracked NXDOMAIN — host does not resolve new — offline
prayer.christchurchmiami.org Not tracked NXDOMAIN — host does not resolve new — offline
app.christchurchmiami.org Cloudflare Pages app, ~2 days live, 3 critical / 4 high / 5 medium findings (APP-1..APP-12) NXDOMAIN — host does not resolve regression — offline
resources.christchurchmiami.org SermonShots subdomain, sunset path pending 301 from vendor SermonSend SvelteKit SPA, 200 OK but canonical points at a logo PNG, 583 bytes visible text, 0 sitemap URLs stable — leaking
The 5/9 audit verified findings against app.christchurchmiami.org as a live Cloudflare Pages deployment (finding A3 explicitly says "Verified live 2026-05-09"). Today's probe confirms the host is no longer in DNS. Whether this is intentional (e.g., DNS repointed during a deploy and not restored) or accidental, the previously-verified APP-1 through APP-12 findings are now blocked behind getting the subdomain back online.

New findings opened this pass

CRITDNS-1es.christchurchmiami.org returns NXDOMAIN — Spanish subdomain advertised in hreflang is not live

The main site's homepage HTML declares Spanish alternate via <link rel="alternate" hreflang="es" href="https://es.christchurchmiami.org/"> alongside an en and x-default. But dig +short es.christchurchmiami.org @1.1.1.1 returns empty — the subdomain has no DNS record.

Why it mattersGoogle interprets hreflang pairs reciprocally. A declared alternate that returns NXDOMAIN is a misconfigured signal — at best, Google ignores the hreflang entirely; at worst, it can affect indexation of the en page or surface mixed-locale results in SERPs. Manual inspection of GSC's International Targeting report after this lands is recommended.
Fix (~15 min)Three options, ordered by reversibility: (a) point es.christchurchmiami.org CNAME at the rendered Spanish content if it exists somewhere; (b) remove the hreflang declaration from the en page (Snappages-side edit); (c) repoint the hreflang at /spanish-sermons or whatever Spanish path lives on the main domain.
CRITDNS-2prayer.christchurchmiami.org returns NXDOMAIN — prayer wall subdomain is not live

Workspace memory references a multi-tenant prayer wall project (project_prayer_wall_multitenant) where the prayer subdomain is designed for CCM first. DNS confirms the subdomain does not currently resolve.

Fix (~30 min)If prayer.cm is intended to be live, add CNAME to the prayer-wall Pages project. If still pre-launch, remove any internal links + sitemap entries pointing at it from the main site to avoid 404s on outbound crawls.
CRITDNS-3app.christchurchmiami.org returns NXDOMAIN — regression from 2026-05-09

The 2026-05-09 audit verified the app subdomain as live ("Cloudflare Pages app, ~2 days live") and identified APP-1 through APP-12. As of 2026-05-14, dig +short app.christchurchmiami.org @1.1.1.1 returns empty.

Why it mattersEither the subdomain was intentionally taken down (in which case CLAUDE.md, the URL map, and the sermon-page-weekly skill design need updates), or this is an accidental regression from a deploy or DNS change. Either way, the 2-day-old Cloudflare Pages app referenced in the 5/9 audit is no longer publicly reachable.
Fix (~30 min)Check the Cloudflare Pages project for app.cm. If the custom-domain CNAME was removed, re-add. If the Pages project was deleted, redeploy from the source repo (per reference_app_christchurchmiami: GitHub at Humble-Disruption/app-christchurchmiami-org). Confirm in browser before claiming resolved.
CRITRES-1resources.christchurchmiami.org SermonSend SPA — canonical points at a logo PNG, 583 bytes visible text

The subdomain serves a SvelteKit SPA. Parsing the HTML: <link rel="canonical" href="/_app/immutable/assets/S%20SEND%20LOGO%20ORIGINAL.BFgn2FyZ.png">. No meta description, no og:image, no JSON-LD blocks, no h1. The visible-text estimate is 583 bytes — well under the 1 KB SPA-shell threshold. /sitemap.xml returns 200 but lists 0 URLs.

Why it mattersThis is the "leaking" state the 5/9 audit flagged. The vendor template (SermonSend) controls the SPA shell — CCM cannot fix the canonical or schema without a vendor change. Until the 301 from resources.cm/*app.cm lands (per 5/9 audit's URL mapping table), this subdomain is bleeding link equity and confusing crawlers.
Fix (vendor-blocked)The fix is the SermonShots support ticket from the 2026-05-09 audit's "cleanup checklist" — site-wide 301 with the documented URL mapping. Once app.cm is back online (see DNS-3 above), this becomes the dependency unblocking everything else.
LOWCCM-15christchurchmiami.org homepage missing og:image and og:title

Probe parsed the homepage meta block: 17 JSON-LD types, hreflang declared, canonical present, meta description present, robots OK, sitemap 84 URLs. But og:title and og:image are both absent from the homepage head. Twitter and Slack scrapers fall back to <title> and image-from-first-img — which is functional but leaves the social-share preview to chance.

Fix (~10 min)In Snappages homepage settings (SEO panel): set OG Title to "Christchurch Miami | Church in Kendall FL 33156" (matches <title>) and OG Image to a 1200×630 brand-card image. Verify by hitting https://opengraph.xyz/url/https%3A%2F%2Fchristchurchmiami.org after.

Carried-over from 2026-05-09 re-verified or unchanged

The 5/9 audit's findings against christchurchmiami.org remain open (the main site itself hasn't materially changed in 5 days). Specifically: CCM-1 through CCM-14. The findings against app.christchurchmiami.org (APP-1..APP-12) are now blocked behind DNS-3 — they can't be re-verified until the subdomain is back online.

IDSeverityTitleStatus
CCM-1crit/en-espanol returns 404 — Ad Grant blockeropen
CCM-2highLegacy About-tier pages missing title/meta/canonical/schemaopen
CCM-3high/giving redirect chain — Ad Grant policy concernopen
CCM-4high/sermons-and-blogs not in primary navigationopen
CCM-5highBlog index meta description is mission statementopen
CCM-7highBlog tag taxonomy bloated (80+ tags)open
CCM-8medOlder blog posts predate the 11-entity @graphopen
CCM-9medImage alt text gap on legacy pagesopen
CCM-10medFive /sermons* pages cannibalize each otheropen
CCM-11medog:image protocol mismatch (http://) on blog postsopen
CCM-13medFAQ count varies post-to-post (6, 9, 11)open
CCM-14low/resources menu page may cannibalize subdomainopen
APP-1..APP-12All 12 app.cm findingsblocked on DNS-3

Comparative — peer matrix (refresh from 2026-05-09)

The 5/9 manual comparative matrix is preserved in the dashboard. Today's automated probe confirms the peer reachability and body-size profile:

PeerStatusBody sizeJSON-LD blocksH1 countNote
Christ Journey200291 KB10Default WordPress; large content library
Christ Fellowship Miami2001.6 MB37Wix; aggressive local SEO
Granada Church200795 KB10Older WordPress build
Old Cutler Presbyterian200114 B00JS redirect script → /lander; thin landing
Vous Church20087 KB01Webflow build; zero JSON-LD
Christchurch Miami20053.8 KB4+317 distinct JSON-LD types — dominates peers

CCM ships a tighter HTML payload (lowest body size of the responding peers) with the strongest JSON-LD breadth (17 distinct types vs. max 3 at any peer). The 5/9 audit's qualitative aggregate (CCM tied with CFM/CJ at 35) still stands directionally — and the schema gap measured today is the largest single CCM moat.

Methodology — how the composite score is computed

Each tracked CCM surface earns up to 100 points, summed and averaged across the 5 tracked surfaces. Surfaces that don't resolve in DNS score 0. The probe runs daily at 06:00 EST via the scheduled-tasks system; see tools/seo_dashboard/probe.py.

SignalPoints
Online & 2xx response30
JSON-LD schema present10
Title, meta description, canonical, og:image (5 each)20
og:title (3), hreflang/EN-only OK (5)8
Robots.txt + sitemap.xml reachable (5 each)10
H1 present + non-trivial body + visible text > 1KB (5 each)15
html lang attribute2
Max100

The formula is intentionally simple — it surfaces gross gaps (missing tags, offline subdomains) rather than nuanced quality differences. The narrative audit (this document) is where qualitative judgment lives. The formula's role is to give Jeff a daily-trackable number that future passes can compare against apples-to-apples.

Recommended next 25 minutes

  1. Decide on app.christchurchmiami.org (DNS-3). If it should be live, fix the DNS/Pages config. If it's intentionally down, update CLAUDE.md + URL map. ~5 min decision, 15 min execution if restoring.
  2. Decide on the hreflang declaration (DNS-1). Either bring up es.christchurchmiami.org or remove the broken alternate from the main site. ~5 min decision, 5 min execution.
  3. Open the SermonShots 301 ticket if not already filed (RES-1 / 5/9 audit's cleanup checklist). ~5 min email.

These three actions clear all four new critical findings opened in this pass and unblock the path back to the trajectory the 5/9 audit was on.