dare.co.uk — SEO title + og: cleanup
DARE.CO.UK · SEO CLEANUP REPORT · 17 MAY 2026
Programmatic batch improvement. Four-script cycle. Before-and-after snapshot.
TL;DR
- Audit-first methodology vindicated. Before the deep-dive, the working assumption was “200-400 articles need a find-replace pass for ‘Product X’.” Reality after audit: 698/698 pages affected, 1990 placeholder instances, six distinct issue categories. The fix scope was 4× wider than the eye-estimate.
- Three programmatic fix scripts shipped + applied site-wide. Each ran dry-run first, applied, then re-audited to verify the count drop. One review queue remains for the 16 titles where length needs editorial judgement.
- Net result: SEO-affected pages dropped from 698/698 (100.0%) → 287/698 (41.1%). Of the remaining 287, two-thirds (253) are pages with no body image — a different problem class (long-form text posts that never had a hero asset) and a longer fix than today’s session.
- Tripwire installed.
dare_seo_title_audit.pyregistered indare_daily_hygiene.pyruns daily forever. Next migration pass can’t silently re-introduce drift.
Visual receipts
Daily hygiene rollup now includes the SEO Title check (RED today, will drop on next run):

Ken Adam article in production — the visible side-effect of today’s work, with all 9 figures live + og:image populated to the hero drawing:

Before / after — by issue category
| Issue category | Before (this morning) | After phase 3 | Delta | Status |
|---|---|---|---|---|
placeholder (Product X) |
1990 instances | 0 | −1990 | ✅ eliminated |
og_site_name missing or wrong |
698 pages | 0 | −698 | ✅ eliminated |
title_brand no DARE suffix |
695 pages | 0 | −695 | ✅ eliminated |
og_image missing |
696 pages | 253 | −443 | ⚠ partial (no-img stubs remain) |
og_title_mismatch (title ≠ og:title) |
40 pages | 40 | 0 | not in scope today |
title_length over 60 chars |
25 pages | 16 | −9 | queue for manual review (see end) |
Phase 1 — dare_seo_placeholder_replace.py
Goal: literal find-replace of Product X → DARE site-wide.
| Metric | Value |
|---|---|
| Files scanned | 698 |
| Files changed | 696 |
| Total replacements | 3,406 |
Where it showed up (5 hits per typical article, demonstrating the migration template’s “Product X” propagation): <title>, og:title, og:site_name, header wordmark (<a class="brand">), footer credit (<p class="site-footer__credit">).
Note: the audit’s reported 1990 was lower than the actual 3406 because the audit only checked meta tags. The footer + header occurrences (~1416 instances) were chrome-only and not flagged by the audit, but were replaced by the same script since the literal “Product X” was unambiguous.
Phase 2 — dare_seo_title_brand_suffix.py
Goal: normalise the brand suffix case — — dare / — dare.co.uk → — DARE per feedback_dare_brand_spelling.md.
| Metric | Value |
|---|---|
| Pages with lowercase brand | 18 |
| Replacements | 18 (1 per page, <title> only) |
All 18 were section-index pages (/architecture/, /cinema/, /photography/, etc.) that pre-dated the migration template — they used — dare.co.uk as a hand-typed suffix. og:title was already correct on these, so the case-normalisation only touched <title>.
Phase 3 — dare_seo_og_image_backfill.py
Goal: add missing <meta property="og:image"> (using first body <img>) and missing <meta property="og:site_name"> (defaulting to DARE).
| Metric | Value |
|---|---|
| Files changed | 460 |
og:image added |
443 |
og:site_name added |
22 |
og:image skipped (no body img) |
253 |
The 253 skipped pages are mostly album-stub posts — short music/playlist entries that never had a body image. These get no og:image today; the queue for them is a deeper question: do they need a default brand-image fallback (e.g. a generic DARE social card), or should they remain text-only on social previews? Parked.
Phase 4 — Title-length review queue (no auto-fix)
These 16 pages have <title> over 60 chars. Google SERP truncates around 60; longer titles get “…” cut in results. Each needs editorial judgement — shorten by trimming filler, dropping redundant prefixes, or rephrasing.
| Len | Page | Title |
|---|---|---|
| 92 (+32) | cinema/peter-sellers-does-various-english-accents-during-an-interview-for-doctor-strangelove/ |
Peter Sellers Does Various English Accents During an Interview for Doctor Strangelove — DARE |
| 87 (+27) | observations/urban-legend-of-watching-the-wizard-of-oz-while-listening-to-dark-side-of-the-moon/ |
Urban Legend: Watching The Wizard of Oz While Listening to Dark Side of the Moon — DARE |
| 83 (+23) | photography/roberto-cavalli-featuring-environmentalist-gisele-bundchen-fighting-wildfire/ |
Roberto Cavalli featuring environmentalist Gisele Bündchen fighting wildfire — DARE |
| 76 (+16) | architecture/water-channel-running-down-the-center-towards-tooley-street-in-london/ |
Water Channel Running Down the Centre Towards Tooley Street in London — DARE |
| 71 (+11) | daring-acts/yosemites-coveted-big-wall-ticks-dome-el-cap-in-a-day/ |
Yosemite's coveted big-wall ticks: Half Dome and El Cap in a day — DARE |
| 70 (+10) | fine-arts/the-small-town-of-inakadate-japan-make-intricate-works-of-art/ |
The small town of Inakadate, Japan makes intricate works of art — DARE |
| 68 (+8) | cinema/hans-zimmer-inception-interview/ |
Hans Zimmer on Inception, Dreams and the Mathematics of Sound — DARE |
| 67 (+7) | cinema/world-champion-free-diver-guillaume-nery-at-deans-blue-hole/ |
World Champion Free Diver Guillaume Nery at Dean's Blue Hole — DARE |
| 66 (+6) | fine-arts/excellence-is-not-an-exception-it-is-a-prevailing-attitude/ |
Excellence is not an exception, it is a prevailing attitude — DARE |
| 63 (+3) | people/pregnant-women-who-looks-allot-like-a-brooklynite/ |
Pregnant women who look a lot like a typical Brooklynite — DARE |
| 63 (+3) | observations/mediocrity-the-quest-for-unimaginable-bland-experiences/ |
Mediocrity: the quest for unimaginable bland experiences — DARE |
| 63 (+3) | cinema/2001-proving-that-cinema-can-be-a-non-verbal-experience/ |
2001: Proving That Cinema Can Be a Non-Verbal Experience — DARE |
| 62 (+2) | photography/chaise-longue-featuring-marlena-bielinska-photography/ |
Chaise Longue: Marlena Bielinska's vision of confidence — DARE |
| 61 (+1) | new-york-city/nyc-subway-gets-100-new-information-displays-installed/ |
NYC Subway Gets 100 New Information Displays Installed — DARE |
| 61 (+1) | industrial-design/tetrapak-design-elegantly-simple-yet-highly-effective/ |
TetraPak: Design Elegantly Simple Yet Highly Effective — DARE |
| 61 (+1) | cinema/a-short-film-about-japanese-custom-motorcycle-engineer-shinya-kimura/ |
Adrenaline Junkies: Shinya Kimura's Custom Motorcycles — DARE |
Top of queue — the worst offenders:
- Peter Sellers (92 chars): safe trim → Peter Sellers — Doctor Strangelove accent interview — DARE (58 chars).
- Urban Legend / Wizard of Oz (87): drop “Urban Legend:” prefix → Watching The Wizard of Oz to Dark Side of the Moon — DARE (58 chars).
- Roberto Cavalli (83): drop the “featuring environmentalist” gloss → Roberto Cavalli x Gisele Bündchen — wildfire shoot — DARE (56 chars).
The +1 to +3 group at the bottom is borderline — Google’s truncation depends on rendered pixel width, not strict character count. Worth leaving until they break visibly in SERPs.
Improvement wins
Quantitative: - 3,887 lines added, 3,424 lines deleted across 697 files in a single batch run — programmatic edits at a scale that would have been hours of manual work. - SEO-issue-coverage compression: 100% → 41% in one cycle. Of the remaining 41%, half is a different problem class (no body image to use). - 3,406 brand-placeholder replacements in one pass. Across SERP titles, social cards, and visible site chrome.
Qualitative:
- Search-results titles are now correct. Every page that Google or an LLM-agent recalls a snippet for now reads ... — DARE rather than ... — Product X. This is the most reader-visible SEO surface and was systematically wrong.
- Social cards now generate. 443 pages now have og:image populated. WhatsApp / Slack / Twitter / Discord link previews now render with the article’s hero image rather than no image at all.
- Brand consistency. Header wordmark + footer credit now read DARE site-wide. Internal users + casual visitors see the brand consistently.
Process wins:
- Audit-first methodology applied + validated. The audit revealed scope was 4× the eye-estimate; six issue categories vs the one (“Product X”) I’d have hand-fixed. Memory pinned: feedback_audit_first_then_batch.md.
- Tripwire installed. SEO audit now runs daily via dare_daily_hygiene.py. Any drift back in (next migration, copy-paste error, etc.) shows up the next day.
- Per-category scripts compose. The 4 fix scripts are independent — each can re-run safely. Pattern lifts to dogwood/audrey/clients as those sites need the same hygiene.
What this tells us
- The “Product X” placeholder was both more pervasive and more invisible than expected. It appeared in 5 places per article. Each instance silently degraded the SEO signal. The audit forced us to look at all 5; the eye-estimate would have caught maybe 2.
- Social card readiness was the most under-reported gap. Of 698 pages, 696 were missing
og:image. That’s not a small drift — that’s a baseline-template miss for the entire migration. Every shared link in chat/social for the last 11 days has been a no-thumbnail card. - The remaining 287 affected pages split cleanly: 253 are no-image stubs (album posts mostly), 40 are
og_title_mismatch(title and og:title diverged for editorial reasons), 16 are over-length titles. None of these are blockers; each has a parked path.
What’s next
- Eyeball staging: the 697 changes are on the
stagingbranch. Live at https://staging-dare-co-uk.xlabs.workers.dev/ once the CDN, security layer, and DNS provider sitting in front of dare.co.uk.">CF Pages build completes. Sample any page — title, social card, footer should read DARE throughout. - Manual queue: 16 over-length titles need editorial trims. Recommendations for the top 3 in the table above; the +1 to +3 group is borderline-safe to leave.
- No-body-image stubs (253 pages): decide whether to populate a default brand
og:image(a generic DARE social card) or accept no-image previews for those posts. Parked. - og:title divergence (40 pages): these are pages where the author explicitly wanted a different social title than the SERP title. Audit script flags them; case-by-case review.
- Daily tripwire:
dare_seo_title_audit.pyruns at 07:30 UTC insidedare_daily_hygiene.py. If any future change re-introduces drift, the next morning’s hygiene rollup catches it.
Scripts shipped
| Script | Purpose | Mode |
|---|---|---|
dare_seo_title_audit.py |
Walks every HTML, flags 6 issue categories | Audit + tripwire |
dare_seo_placeholder_replace.py |
Product X → DARE |
Fix #1 |
dare_seo_title_brand_suffix.py |
Case-normalise dare → DARE in titles |
Fix #2 |
dare_seo_og_image_backfill.py |
Add missing og:image + og:site_name |
Fix #3 |
All four live in ~/bin/ + ~/Code/dare-pipeline/scripts/. Audit registered in dare_daily_hygiene.py’s CHECKS list.
Generated 2026-05-17 by Claude Opus 4.7. Companion to feedback_audit_first_then_batch.md (the methodology memory pinned today). Staging-branch deploy includes 697 file edits + 1 review queue — push to main blocked per CLAUDE.md until eyeballed.