Feat/SW-2152 seo descriptions

* feat(SW-2152): Added improved meta descriptions for hotel pages
* feat(SW-2152): Added improved meta descriptions for destination pages
* feat(SW-2152): Refactoring metadata description functionality
* feat(SW-2152): Improved truncate function and added cities check to country page description

Approved-by: Michael Zetterberg
Approved-by: Matilda Landström
This commit is contained in:
Erik Tiekstra
2025-04-29 06:52:04 +00:00
parent 70095043f8
commit 4ae5da8a04
13 changed files with 768 additions and 531 deletions

View File

@@ -11,10 +11,13 @@ import { additionalDataAttributesSchema } from "../../hotels/schemas/hotel/inclu
import { imageSchema } from "../../hotels/schemas/image"
import { tempImageVaultAssetSchema } from "../schemas/imageVault"
import { systemSchema } from "../schemas/system"
import { getDescription, getImage, getTitle } from "./utils"
import { getDescription } from "./utils/description"
import { getImage } from "./utils/image"
import { getTitle } from "./utils/title"
import type { Metadata } from "next"
import type { ImageVaultAsset } from "@/types/components/imageVault"
import { Country } from "@/types/enums/country"
import type { LanguageSwitcherData } from "@/types/requests/languageSwitcher"
import { RTETypeEnum } from "@/types/rte/enums"
@@ -57,56 +60,59 @@ export const rawMetadataSchema = z.object({
.object({
seo_metadata: z
.object({
title: z.string().optional().nullable(),
description: z.string().optional().nullable(),
noindex: z.boolean().optional().nullable(),
title: z.string().nullish(),
description: z.string().nullish(),
noindex: z.boolean().nullish(),
seo_image: tempImageVaultAssetSchema.nullable(),
})
.optional()
.nullable(),
.nullish(),
breadcrumbs: z
.object({
title: z.string().optional().nullable(),
title: z.string().nullish(),
})
.optional()
.nullable(),
.nullish(),
})
.optional()
.nullable(),
.nullish(),
destination_settings: z
.object({
city_denmark: z.string().optional().nullable(),
city_finland: z.string().optional().nullable(),
city_germany: z.string().optional().nullable(),
city_poland: z.string().optional().nullable(),
city_norway: z.string().optional().nullable(),
city_sweden: z.string().optional().nullable(),
country: z.nativeEnum(Country).optional().nullable(),
city_denmark: z.string().nullish(),
city_finland: z.string().nullish(),
city_germany: z.string().nullish(),
city_poland: z.string().nullish(),
city_norway: z.string().nullish(),
city_sweden: z.string().nullish(),
country: z.nativeEnum(Country).nullish(),
})
.optional()
.nullable(),
heading: z.string().optional().nullable(),
preamble: z.string().optional().nullable(),
.nullish(),
heading: z.string().nullish(),
preamble: z.string().nullish(),
header: z
.object({
heading: z.string().optional().nullable(),
preamble: z.string().optional().nullable(),
heading: z.string().nullish(),
preamble: z.string().nullish(),
hero_image: tempImageVaultAssetSchema.nullable(),
})
.optional()
.nullable(),
.nullish(),
hero_image: tempImageVaultAssetSchema.nullable(),
images: z
.array(z.object({ image: tempImageVaultAssetSchema }).nullish())
.transform((images) =>
images
.map((image) => image?.image)
.filter((image): image is ImageVaultAsset => !!image)
)
.nullish(),
blocks: metaDataBlocksSchema,
hotel_page_id: z.string().optional().nullable(),
hotel_page_id: z.string().nullish(),
hotelData: hotelAttributesSchema
.pick({
name: true,
address: true,
detailedFacilities: true,
hotelContent: true,
healthFacilities: true,
})
.optional()
.nullable(),
.nullish(),
additionalHotelData: additionalDataAttributesSchema
.pick({
gallery: true,
@@ -118,28 +124,31 @@ export const rawMetadataSchema = z.object({
accessibility: true,
conferencesAndMeetings: true,
})
.optional()
.nullable(),
.nullish(),
hotelRestaurants: z
.array(
z.object({
nameInUrl: z.string().optional().nullable(),
elevatorPitch: z.string().optional().nullable(),
name: z.string().optional().nullable(),
nameInUrl: z.string().nullish(),
elevatorPitch: z.string().nullish(),
name: z.string().nullish(),
content: z
.object({
images: z.array(imageSchema).optional().nullable(),
images: z.array(imageSchema).nullish(),
})
.optional()
.nullable(),
.nullish(),
})
)
.optional()
.nullable(),
subpageUrl: z.string().optional().nullable(),
location: z.string().optional().nullable(),
filter: z.string().optional().nullable(),
filterType: z.enum(["facility", "surroundings"]).optional().nullable(),
.nullish(),
subpageUrl: z.string().nullish(),
destinationData: z
.object({
location: z.string().nullish(),
filter: z.string().nullish(),
filterType: z.enum(["facility", "surroundings"]).nullish(),
hotelCount: z.number().nullish(),
cities: z.array(z.string()).nullish(),
})
.nullish(),
system: systemSchema,
})
@@ -149,7 +158,7 @@ export const metadataSchema = rawMetadataSchema.transform(async (data) => {
const metadata: Metadata = {
metadataBase: env.PUBLIC_URL ? new URL(env.PUBLIC_URL) : undefined,
title: await getTitle(data),
description: getDescription(data),
description: await getDescription(data),
openGraph: {
images: getImage(data),
},