Skip to content

Add manual page title overrides - #4079

Open
theletterf wants to merge 8 commits into
feature/3938-product-title-fallbackfrom
feature/3938-meta-title
Open

theletterf wants to merge 8 commits into
feature/3938-product-title-fallbackfrom
feature/3938-meta-title

Conversation

@theletterf

@theletterf theletterf commented Sep 14, 2026

Copy link
Copy Markdown
Member

Authors can override the automatic H1 and product-derived title with meta_title without changing the visible heading, navigation label, or indexed title. The override also works for authored Markdown embedded in API reference pages and Codex pages.

Affects: Authoring, API reference, Codex builds

Prompt summary: Keep the product-aware title from the H1 as the SEO fallback, and provide a manual override only as a last resort. Stack this override on the automatic title behavior in #4083.

Why

The automatic product qualifier covers the standard SEO cases, but some pages still need exceptional wording in browser tabs and search metadata. Authored API Markdown also needs to carry this metadata through its separate rendering path without changing its H1 or breadcrumb.

What

Manual title precedence

The Markdown frontmatter parser accepts meta_title: and normalizes substitutions and Markdown formatting. A non-empty override takes precedence over the automatic H1 and product title, while the builder still owns the site suffix.

Embedded API Markdown

The Markdown string renderer returns parsed H1 and metadata separately for authored API pages. API layouts use the metadata title when present but retain the H1 for visible headings and breadcrumbs.

Shared rendering

Standard and Codex page layouts consume the same resolved page title. Parsed headings preserve their visible Markdown formatting while metadata uses plain text.

Authoring guidance

The frontmatter and title guides present meta_title as a last-resort override after the automatic product fallback. Related hub and API guidance distinguishes the visible heading from metadata.

Verify

dotnet test tests/Elastic.Markdown.Tests/
dotnet test tests/Elastic.ApiExplorer.Tests/

Stack: 2 of 2, on top of #4083.

Closes #3938.

@github-actions

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes due to an incorrect title-derivation path that can emit wrong metadata titles when non-heading # lines appear before the real H1.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

Comment thread src/Elastic.ApiExplorer/Navigation/MarkdownNavigationTitleReader.cs Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes: one medium-severity issue needs to be addressed before merge.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

Comment thread src/Elastic.ApiExplorer/Navigation/MarkdownNavigationTitleReader.cs Outdated

@Mpdreamz Mpdreamz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hate to introduce three ways to set titles but I can see this becoming unavoidable.

We should still warn/error on 1 word H1 titles too I think.

@Mpdreamz

Copy link
Copy Markdown
Member

Does this fully replace the meta title? We still want our suffixes.

@theletterf

theletterf commented Sep 14, 2026

Copy link
Copy Markdown
Member Author

@Mpdreamz meta_title replaces only the page-specific part. The builder still appends the suffix. Public assembler builds use | Elastic Docs, while custom-branded and isolated builds keep their existing suffixes.

Besides reading the H1 and setting a meta_title, what's the other?

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes: there is one medium-severity regression that should be fixed before merge.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

Comment thread src/Elastic.Markdown/IO/MarkdownFile.cs Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APPROVE


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

@theletterf

Copy link
Copy Markdown
Member Author

+CC @georgewallace @celiaggg Implemented as per the issue.

@theletterf
theletterf force-pushed the feature/3938-meta-title branch from c73555a to 4f8ea5a Compare September 14, 2026 10:25
@theletterf theletterf changed the title Add independent page titles for SEO Add manual page title overrides Sep 14, 2026
@theletterf
theletterf changed the base branch from main to feature/3938-product-title-fallback September 14, 2026 10:25

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes: one medium-severity regression needs to be fixed before merge.


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

Comment thread src/Elastic.Markdown/HtmlWriter.cs Outdated
var parsed = DocumentationSet.MarkdownParser.ParseStringAsync(markdown, source, null);
return new(
MarkdownFile.CreateHtml(parsed, stripFirstHeadingLevel1: false),
MarkdownFile.ReadTitle(parsed)?.StripMarkdown(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] API markdown H1 titles bypass substitution expansion

RenderPreservingFirstHeadingWithMetadata() derives Title from MarkdownFile.ReadTitle(parsed)?.StripMarkdown(). ReadTitle() returns the heading text captured by HeadingBlockWithSlugParser (SetData("header", ...)) before {{...}} substitutions are rendered, so API authored pages can get a raw template title in metadata/breadcrumbs.

Concrete repro:

---
sub:
  product: Elasticsearch
---

# {{product}} query guide

The rendered H1 becomes Elasticsearch query guide, but PageTitle (and therefore layout title/breadcrumb current title) is {{product}} query guide. Please resolve substitutions for this title path (or derive the title from already-rendered heading content) so metadata and breadcrumb titles stay consistent with the visible heading.

@theletterf

Copy link
Copy Markdown
Member Author

@Mpdreamz Could you reapprove this one while I research impact on sitemap?

@Mpdreamz Mpdreamz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, is #4079 (comment) still active?

theletterf and others added 8 commits September 15, 2026 14:24
Let authors and generated API pages add search context without changing visible headings or navigation labels.

Co-Authored-By: Codex <noreply@anthropic.com>
Use the parsed heading tree so frontmatter and code examples cannot become page titles.

Co-Authored-By: Codex <noreply@anthropic.com>
Route authored API metadata through the same substitution and formatting cleanup as standard pages.

Co-Authored-By: Codex <noreply@anthropic.com>
Keep raw heading Markdown for visible H1 rendering while API metadata uses plain text.

Co-Authored-By: Codex <noreply@anthropic.com>
Explain the automatic product fallback first so authors reserve manual metadata titles for exceptional wording.

Co-Authored-By: GPT-5.6 Sol <noreply@anthropic.com>
Keep manual override guidance aligned with the shared product inference used by the automatic fallback.

Co-Authored-By: GPT-5.6 Sol <noreply@anthropic.com>
Co-Authored-By: GPT-5.6 Sol <noreply@anthropic.com>
Merged ReadTitle and ReadMetaTitle into a single ReadTitles method that
parses frontmatter once and applies substitutions to both title and
meta_title before returning. Previously, RenderPreservingFirstHeadingWithMetadata
returned raw pre-substitution text (e.g. "{{product}} query guide") for
the Title field because ReadTitle read the heading text before any
{{key}} expansion had run.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

APPROVE


What is this? | From workflow: PR Review

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.

@georgewallace

Copy link
Copy Markdown
Contributor

Please hold off on merging until I can fully test and verify this works as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add meta_title frontmatter field to docs-builder

3 participants