Merged in SW-3490-set-metadata-for-routes (pull request #2881)

SW-3490 set metadata for routes
* feat(SW-3490): Set metadata title for hotelreservation paths

Approved-by: Anton Gunnarsson
This commit is contained in:
Joakim Jäderberg
2025-10-01 11:34:52 +00:00
parent 4f151b143e
commit df8e223d23
25 changed files with 440 additions and 37 deletions

View File

@@ -27,6 +27,7 @@ export async function generateMetadata({
const { subpage, filterFromUrl, ...otherSearchParams } = await searchParams
// If there are other (real) search params, we don't want to index the page as this will
// cause duplicate content issues.
const noIndexOnSearchParams = !!Object.keys(otherSearchParams).length
const caller = await serverClient()
const { rawMetadata, alternates, robots } =
@@ -129,7 +130,7 @@ async function getTransformedMetadata(
) {
const metadata: Metadata = {
metadataBase: env.PUBLIC_URL ? new URL(env.PUBLIC_URL) : undefined,
title: await getTitle(data),
title: { absolute: await getTitle(data) },
description: await getDescription(data),
openGraph: {
images: getImage(data),

View File

@@ -4,8 +4,7 @@ import type { RawMetadataSchema } from "@scandic-hotels/trpc/routers/contentstac
export async function getDestinationPageTitle(
data: RawMetadataSchema,
pageType: "city" | "country",
suffix: string
pageType: "city" | "country"
) {
const intl = await getIntl()
const { destinationData } = data
@@ -33,13 +32,10 @@ export async function getDestinationPageTitle(
{ location }
)
return `${destinationTitle}${suffix}`
return destinationTitle
}
export function getDestinationFilterSeoMetaTitle(
data: RawMetadataSchema,
suffix: string
) {
export function getDestinationFilterSeoMetaTitle(data: RawMetadataSchema) {
const filter = data.destinationData?.filter
if (!filter) {
@@ -51,10 +47,10 @@ export function getDestinationFilterSeoMetaTitle(
if (foundSeoFilter) {
if (foundSeoFilter.seo_metadata?.title) {
return `${foundSeoFilter.seo_metadata.title}${suffix}`
return foundSeoFilter.seo_metadata.title
}
return `${foundSeoFilter.heading}${suffix}`
return foundSeoFilter.heading
}
return null

View File

@@ -0,0 +1,11 @@
import { env } from "@/env/server"
export function getTitlePrefix() {
if (env.SENTRY_ENVIRONMENT === "production") {
return ""
}
const environmentShortName =
env.SENTRY_ENVIRONMENT === "development" ? "local" : env.SENTRY_ENVIRONMENT
return `${environmentShortName}`
}

View File

@@ -4,6 +4,7 @@ import {
getDestinationFilterSeoMetaTitle,
getDestinationPageTitle,
} from "./destinationPage"
import { getTitlePrefix } from "./getTitlePrefix"
import { getHotelPageTitle } from "./hotelPage"
import type { RawMetadataSchema } from "@scandic-hotels/trpc/routers/contentstack/metadata/output"
@@ -17,13 +18,14 @@ function getTitleSuffix(contentType: string) {
case PageContentTypeEnum.destinationOverviewPage:
case PageContentTypeEnum.destinationCityPage:
case PageContentTypeEnum.destinationCountryPage:
return " | Scandic Hotels"
return "Scandic Hotels"
default:
return ""
}
}
export async function getTitle(data: RawMetadataSchema) {
const prefix = getTitlePrefix()
const suffix = getTitleSuffix(data.system.content_type_uid)
const metadata = data.web?.seo_metadata
const isDestinationPage = [
@@ -32,48 +34,41 @@ export async function getTitle(data: RawMetadataSchema) {
].includes(data.system.content_type_uid as PageContentTypeEnum)
if (isDestinationPage) {
const destinationFilterSeoMetaTitle = getDestinationFilterSeoMetaTitle(
data,
suffix
)
const destinationFilterSeoMetaTitle = getDestinationFilterSeoMetaTitle(data)
if (destinationFilterSeoMetaTitle) {
return destinationFilterSeoMetaTitle
}
}
if (metadata?.title) {
return `${metadata.title}${suffix}`
return combineSegments([prefix, metadata.title, suffix])
}
let title: string | null = null
let title: string | null | undefined = null
switch (data.system.content_type_uid) {
case PageContentTypeEnum.hotelPage:
title = await getHotelPageTitle(data)
break
case PageContentTypeEnum.destinationCityPage:
title = await getDestinationPageTitle(data, "city", suffix)
title = await getDestinationPageTitle(data, "city")
break
case PageContentTypeEnum.destinationCountryPage:
title = await getDestinationPageTitle(data, "country", suffix)
title = await getDestinationPageTitle(data, "country")
break
default:
break
}
if (title) {
return title
}
// Fallback titles from contentstack content
if (data.web?.breadcrumbs?.title) {
return `${data.web.breadcrumbs.title}${suffix}`
}
if (data.heading) {
return `${data.heading}${suffix}`
}
if (data.header?.heading) {
return `${data.header.heading}${suffix}`
}
return ""
title ||= data.web?.breadcrumbs?.title || data.heading || data.header?.heading
return combineSegments([prefix, title, suffix])
}
function combineSegments(
segments: (string | null | undefined)[],
delimiter = " | "
) {
return segments.filter(Boolean).join(delimiter).trim()
}