diff --git a/src/components/PageHead.astro b/src/components/PageHead.astro index 0cc5330eea2..aa083aa1b29 100644 --- a/src/components/PageHead.astro +++ b/src/components/PageHead.astro @@ -17,6 +17,7 @@ import { classifyContentType, inferContentType, resolveFavicon, + resolvePageHeadline, resolvePageTitle, resolveSocialImagePath, } from "~/util/page-head"; @@ -110,6 +111,7 @@ const fullTitle = resolvePageTitle({ titleSuffix, siteTitle: config.title, }); +const structuredHeadline = resolvePageHeadline({ title, titleOverride }); // Parity: no site-wide fallback — an absent description omits the tags. const resolvedDescription = description; @@ -175,7 +177,7 @@ const datePublished = meta?.datePublished const jsonLd = buildStructuredData({ schemaType: resolvedSchemaType, canonical, - fullTitle, + headline: structuredHeadline, description: structuredDescription, lang, ogImage, diff --git a/src/util/__snapshots__/page-head.node.test.ts.snap b/src/util/__snapshots__/page-head.node.test.ts.snap index 722513fd5e2..d2922ede024 100644 --- a/src/util/__snapshots__/page-head.node.test.ts.snap +++ b/src/util/__snapshots__/page-head.node.test.ts.snap @@ -1,3 +1,3 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`buildStructuredData > exact key order + full string (locks byte-for-byte parity) 1`] = `"{"@context":"https://schema.org","@type":"BlogPosting","@id":"https://developers.cloudflare.com/changelog/x/#page","headline":"X · Changelog","description":"desc","url":"https://developers.cloudflare.com/changelog/x/","inLanguage":"en","image":"https://developers.cloudflare.com/og.png","dateModified":"2025-02-02","datePublished":"2025-01-01","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["t1"]}"`; +exports[`buildStructuredData > exact key order + full string (locks byte-for-byte parity) 1`] = `"{"@context":"https://schema.org","@type":"BlogPosting","@id":"https://developers.cloudflare.com/changelog/x/#page","headline":"X","description":"desc","url":"https://developers.cloudflare.com/changelog/x/","inLanguage":"en","image":"https://developers.cloudflare.com/og.png","dateModified":"2025-02-02","datePublished":"2025-01-01","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"},"keywords":["t1"]}"`; diff --git a/src/util/page-head.node.test.ts b/src/util/page-head.node.test.ts index 8effb4d8867..fc1479a6b70 100644 --- a/src/util/page-head.node.test.ts +++ b/src/util/page-head.node.test.ts @@ -5,6 +5,7 @@ import { classifyContentType, inferContentType, resolveFavicon, + resolvePageHeadline, resolvePageTitle, resolveSocialImagePath, } from "./page-head"; @@ -135,10 +136,25 @@ describe("resolvePageTitle", () => { expect( resolvePageTitle({ title: "raw", - titleOverride: "Custom Head Title", + titleOverride: "Custom Head Title | SEO context", siteTitle: "Cloudflare Docs", }), - ).toBe("Custom Head Title"); + ).toBe("Custom Head Title | SEO context"); + }); +}); + +describe("resolvePageHeadline", () => { + test("uses the page title without a product/site suffix", () => { + expect(resolvePageHeadline({ title: "Get started" })).toBe("Get started"); + }); + + test("uses the clean base even when `