Skip to content

Expand the Yoast title templates in seo_title - #225

Merged
ssavutu merged 1 commit into
mainfrom
fix/yoast-title-templates-on-backfill
Sep 1, 2026
Merged

Expand the Yoast title templates in seo_title#225
ssavutu merged 1 commit into
mainfrom
fix/yoast-title-templates-on-backfill

Conversation

@ssavutu

@ssavutu ssavutu commented Sep 1, 2026

Copy link
Copy Markdown
Member

Follow-up to the %%title%% %%page%% browser tab on /article/with-you-rugby-crossword. Scalene PR #102 stops the tokens rendering; this fixes the data they come from.

WordPress stored SEO titles as Yoast templates, and BackfillArticleSEOFromYoast copies them into seo_title verbatim. 79 of 10,190 production articles hold one, all from the 2022–2023 Yoast era, all in seo_title (meta_description, excerpt, title, focus_keyword and canonical_url are clean — checked).

What it does

ExpandYoastTitle mirrors expandSeoVariables in Scalene's src/utils/seoTemplate.ts, so the CMS and the public site agree on what a template means:

  • %%title%%, %%sitename%%, %%primary_category%%, %%sep%% are substituted; %%page%% expands to nothing, as it did under Yoast (it numbers a paginated archive, and an article is one page); anything unrecognised is dropped rather than printed.
  • Punctuation a dropped variable strands is tidied — no title left hanging on a dash.
  • A template that says no more than the headline (Yoast's default, %%title%% %%page%%) is stored blank, not expanded: the site renders the headline for a blank seo_title, auditArticle already treats blank as correct, and it keeps tracking the headline if an editor rewrites it later. 49 of the 79 land here; 30 carry real editor-written titles and keep them.

The pass runs on every start rather than behind the backfill's one-time flag — the databases holding these templates were seeded before this existed, and the backfill only fills blanks. Idempotent: expanded text has no variables, so a second pass matches nothing.

Testing

  • Unit tests over the real production templates (yoast_title_test.go), plus idempotency and the redundant-title rule.
  • Parity check against all 79 live rows: exported them from prod, ran both the Go and the TypeScript implementation over each, 0 differences.
  • go build ./... and go test ./internal/database/ pass.

Deploying this performs the backfill

On the next deploy the startup pass rewrites those 79 rows. Two of them are worth an editor's eye afterwards — their stored templates are malformed, with a note appended after %%sitename%%, and expand faithfully but awkwardly:

  • 8835 the-triangles-guide-to-running-in-philadelphia → The Triangle's guide to running in Philadelphia - The Triangle How to run in Philly
  • 8836 sixers-win-play-in-game-clinch-no-7-seed → Sixers win play-in game, clinch No. 7 seed - The Triangle Sixers win play-in game

Both are editable in the CMS SEO panel; I did not guess at what they were meant to say.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Tx3ywgRQLzzrZWNcSdtTpr

WordPress stored an article's SEO title as a Yoast template rather than
as finished text -- "%%title%% %%page%%", or a headline with "%%page%%
%%sep%% %%sitename%%" appended -- and Yoast substituted the variables
when it rendered the page. BackfillArticleSEOFromYoast copies that value
into seo_title verbatim, and nothing substitutes it now, so the tokens
reach the public site's <title>, og:title and twitter:title as
themselves: a 2022 crossword is "%%title%% %%page%%" in the browser tab,
in search results and on every shared link. 79 of 10,190 articles in
production hold one, all imported from the 2022-2023 Yoast era.

Expand them, mirroring expandSeoVariables in Scalene's seoTemplate.ts so
the CMS and the public site agree on what a template means. %%page%%
expands to nothing, as it did under Yoast -- it numbers a paginated
archive, and an article is one page -- and an unrecognised variable is
dropped rather than printed. A template that says no more than the
headline, which is what Yoast's default meant, is stored blank: the site
renders the headline for a blank seo_title, the SEO audit already treats
that as correct, and it keeps tracking the headline if an editor
rewrites it.

The pass runs on every start rather than behind the backfill's one-time
flag, because the databases that already hold these templates were
seeded before this existed and the backfill only ever fills blanks. It
is idempotent: expanded text carries no variables, so a second pass
matches nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tx3ywgRQLzzrZWNcSdtTpr
@ssavutu
ssavutu merged commit 8343c53 into main Sep 1, 2026
7 checks passed
@ssavutu
ssavutu deleted the fix/yoast-title-templates-on-backfill branch September 1, 2026 22:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant