Merged in feat/enter-details-tracking (pull request #1185)
Feat/enter details tracking * feat: fixed bug in enter details tracking * Sidepeek events, lowestroomPrice and analyticsRateCode * Cleanup and fixed bug * Fixed analyticsratecode * Merge master * merge master * Removed console logs * Added ancillaries tracking to enter details * Added ancillary on confirmation page * Removed console log * Merge branch 'master' into feat/enter-details-tracking * Refactor searchparams * Hard code values for breakfast ancillary Approved-by: Joakim Jäderberg
This commit is contained in:
@@ -75,7 +75,6 @@ export default async function SelectRatePage({
|
||||
country: hotelData?.data?.attributes.address.country,
|
||||
hotelID: hotel?.id,
|
||||
region: hotelData?.data?.attributes.address.city,
|
||||
//lowestRoomPrice:
|
||||
}
|
||||
|
||||
const hotelId = +hotel.id
|
||||
|
||||
@@ -9,6 +9,7 @@ import { createSDKPageObject, pushToDataLayer } from "@/utils/tracking"
|
||||
|
||||
import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
|
||||
import {
|
||||
type Ancillary,
|
||||
TrackingChannelEnum,
|
||||
type TrackingSDKHotelInfo,
|
||||
type TrackingSDKPageData,
|
||||
@@ -35,21 +36,11 @@ export default function EnterDetailsTracking(props: Props) {
|
||||
cancellationRule,
|
||||
} = props
|
||||
|
||||
const {
|
||||
currentStep,
|
||||
bedType,
|
||||
breakfast,
|
||||
totalPrice,
|
||||
roomPrice,
|
||||
roomRate,
|
||||
packages,
|
||||
} = useEnterDetailsStore((state) => state)
|
||||
const { bedType, breakfast, totalPrice, roomPrice, roomRate, packages } =
|
||||
useEnterDetailsStore((state) => state)
|
||||
const pathName = usePathname()
|
||||
const sessionId = useSessionId()
|
||||
|
||||
// We need this check to differentiate hard vs soft navigations
|
||||
// This is not because of StrictMode
|
||||
const hasRunInitial = useRef<boolean>(false)
|
||||
const previousPathname = useRef<string | null>(null)
|
||||
|
||||
const getSpecialRoomType = (packages: Packages | null) => {
|
||||
@@ -77,34 +68,61 @@ export default function EnterDetailsTracking(props: Props) {
|
||||
}
|
||||
}
|
||||
|
||||
const getAnalyticsRateCode = (rateCodeName: string | undefined) => {
|
||||
switch (rateCodeName) {
|
||||
case "FLEXEU":
|
||||
return "flex"
|
||||
case "CHANGEEU":
|
||||
return "change"
|
||||
case "SAVEEU":
|
||||
return "save"
|
||||
default:
|
||||
return rateCodeName
|
||||
}
|
||||
}
|
||||
|
||||
const pageObject = useMemo(() => {
|
||||
const stepByPathname = pathName.split("/").pop()!
|
||||
const pageTrackingData: TrackingSDKPageData = {
|
||||
pageId: currentStep,
|
||||
pageId: stepByPathname,
|
||||
domainLanguage: lang,
|
||||
channel: TrackingChannelEnum["hotelreservation"],
|
||||
pageName: `hotelreservation|${currentStep}`,
|
||||
siteSections: `hotelreservation|${currentStep}`,
|
||||
pageType: currentStep,
|
||||
pageName: `hotelreservation|${stepByPathname}`,
|
||||
siteSections: `hotelreservation|${stepByPathname}`,
|
||||
pageType: stepByPathname,
|
||||
siteVersion: "new-web",
|
||||
}
|
||||
|
||||
const trackingData = {
|
||||
...pageTrackingData,
|
||||
sessionId,
|
||||
pathName,
|
||||
sessionId,
|
||||
pageLoadTime: 0, // Yes, this is instant
|
||||
}
|
||||
const pageObject = createSDKPageObject(trackingData)
|
||||
|
||||
return pageObject
|
||||
}, [currentStep, lang, pathName, sessionId])
|
||||
}, [lang, sessionId, pathName])
|
||||
|
||||
const hotelDetailsData = useMemo(() => {
|
||||
const isMember = true
|
||||
const rate = isMember ? roomRate.memberRate : roomRate.publicRate
|
||||
|
||||
const breakfastAncillary = breakfast && {
|
||||
hotelid: initialHotelsTrackingData.hotelID,
|
||||
productName: "BreakfastAdult",
|
||||
productCategory: "", // TODO: Add category
|
||||
productId: breakfast.code,
|
||||
productPrice: +breakfast.localPrice.price,
|
||||
productUnits: initialHotelsTrackingData.noOfAdults,
|
||||
productPoints: 0,
|
||||
productType: "food",
|
||||
}
|
||||
|
||||
const data: TrackingSDKHotelInfo = {
|
||||
...initialHotelsTrackingData,
|
||||
rateCode: rate?.rateCode,
|
||||
rateCodeType: rate?.rateType,
|
||||
rateCodeType: roomRate.publicRate.rateType,
|
||||
rateCodeName: rate?.rateCode,
|
||||
rateCodeCancellationRule: cancellationRule,
|
||||
revenueCurrencyCode: totalPrice.local?.currency,
|
||||
@@ -119,39 +137,32 @@ export default function EnterDetailsTracking(props: Props) {
|
||||
? roomRate.publicRate.localPrice.pricePerStay -
|
||||
roomRate.memberRate.localPrice.pricePerStay
|
||||
: 0,
|
||||
analyticsrateCode: getAnalyticsRateCode(roomRate.publicRate.rateCode),
|
||||
ancillaries: breakfastAncillary ? [breakfastAncillary] : [],
|
||||
}
|
||||
|
||||
return data
|
||||
}, [
|
||||
roomRate.memberRate,
|
||||
roomRate.publicRate,
|
||||
bedType,
|
||||
breakfast,
|
||||
totalPrice,
|
||||
roomPrice,
|
||||
roomRate,
|
||||
packages,
|
||||
initialHotelsTrackingData,
|
||||
cancellationRule,
|
||||
totalPrice.local?.currency,
|
||||
totalPrice.local?.price,
|
||||
breakfast,
|
||||
packages,
|
||||
selectedRoom.roomType,
|
||||
bedType?.description,
|
||||
bedType?.roomTypeCode,
|
||||
roomPrice.perStay.local.price,
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasRunInitial.current) {
|
||||
hasRunInitial.current = true
|
||||
previousPathname.current = pathName // Set initial path to compare later
|
||||
return
|
||||
if (previousPathname.current !== pathName) {
|
||||
pushToDataLayer({
|
||||
event: "pageView",
|
||||
pageInfo: pageObject,
|
||||
userInfo: userTrackingData,
|
||||
hotelInfo: hotelDetailsData,
|
||||
})
|
||||
}
|
||||
|
||||
//if (previousPathname.current !== pathName) {
|
||||
pushToDataLayer({
|
||||
event: "pageView",
|
||||
pageInfo: pageObject,
|
||||
userInfo: userTrackingData,
|
||||
//hotelInfo: hotelDetailsData,
|
||||
})
|
||||
//}
|
||||
previousPathname.current = pathName // Update for next render
|
||||
}, [userTrackingData, pageObject, hotelDetailsData, pathName])
|
||||
|
||||
|
||||
@@ -162,16 +162,6 @@ export default async function StepPage({
|
||||
const departureDate = new Date(toDate)
|
||||
const hotelAttributes = hotelData?.data.attributes
|
||||
|
||||
const initialPageTrackingData: TrackingSDKPageData = {
|
||||
pageId: searchParams.step,
|
||||
domainLanguage: lang,
|
||||
channel: TrackingChannelEnum["hotelreservation"],
|
||||
pageName: `hotelreservation|${searchParams.step}`,
|
||||
siteSections: `hotelreservation|${searchParams.step}`,
|
||||
pageType: searchParams.step,
|
||||
siteVersion: "new-web",
|
||||
}
|
||||
|
||||
const initialHotelsTrackingData: TrackingSDKHotelInfo = {
|
||||
searchTerm: searchParams.city,
|
||||
arrivalDate: format(arrivalDate, "yyyy-MM-dd"),
|
||||
@@ -297,12 +287,6 @@ export default async function StepPage({
|
||||
cancellationRule={roomAvailability.cancellationText}
|
||||
lang={lang}
|
||||
/>
|
||||
<Suspense fallback={null}>
|
||||
<TrackingSDK
|
||||
pageData={initialPageTrackingData}
|
||||
hotelInfo={initialHotelsTrackingData}
|
||||
/>
|
||||
</Suspense>
|
||||
</EnterDetailsProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
type TrackingSDKPageData,
|
||||
type TrackingSDKPaymentInfo,
|
||||
} from "@/types/components/tracking"
|
||||
import { BreakfastPackageEnum } from "@/types/enums/breakfast"
|
||||
|
||||
export default async function BookingConfirmation({
|
||||
confirmationNumber,
|
||||
@@ -27,6 +28,21 @@ export default async function BookingConfirmation({
|
||||
const arrivalDate = new Date(booking.checkInDate)
|
||||
const departureDate = new Date(booking.checkOutDate)
|
||||
|
||||
const breakfastPkgSelected = booking.packages.find(
|
||||
(pkg) => pkg.code === BreakfastPackageEnum.REGULAR_BREAKFAST
|
||||
)
|
||||
|
||||
const breakfastAncillary = breakfastPkgSelected && {
|
||||
hotelid: hotel.operaId,
|
||||
productName: "BreakfastAdult",
|
||||
productCategory: "", // TODO: Add category
|
||||
productId: breakfastPkgSelected.code ?? "",
|
||||
productPrice: +breakfastPkgSelected.unitPrice,
|
||||
productUnits: booking.adults,
|
||||
productPoints: 0,
|
||||
productType: "food",
|
||||
}
|
||||
|
||||
const initialPageTrackingData: TrackingSDKPageData = {
|
||||
pageId: "booking-confirmation",
|
||||
domainLanguage: lang,
|
||||
@@ -70,6 +86,7 @@ export default async function BookingConfirmation({
|
||||
roomTypeCode: booking.roomTypeCode ?? undefined,
|
||||
roomPrice: booking.roomPrice,
|
||||
bnr: booking.confirmationNumber ?? undefined,
|
||||
ancillaries: breakfastAncillary ? [breakfastAncillary] : [],
|
||||
}
|
||||
|
||||
const paymentInfo: TrackingSDKPaymentInfo = {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
"use client"
|
||||
|
||||
import { useSearchParams } from "next/navigation"
|
||||
import { useCallback, useEffect, useMemo, useState } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { trackLowestRoomPrice } from "@/utils/tracking"
|
||||
|
||||
import RoomFilter from "../RoomFilter"
|
||||
import RoomSelection from "../RoomSelection"
|
||||
import { filterDuplicateRoomTypesByLowestPrice } from "./utils"
|
||||
@@ -28,6 +31,12 @@ export default function Rooms({
|
||||
hotelType,
|
||||
isUserLoggedIn,
|
||||
}: SelectRateProps) {
|
||||
const searchParams = useSearchParams()
|
||||
|
||||
const hotelId = searchParams.get("hotel")
|
||||
const arrivalDate = searchParams.get("fromDate")
|
||||
const departureDate = searchParams.get("toDate")
|
||||
|
||||
const intl = useIntl()
|
||||
|
||||
const visibleRooms: RoomConfiguration[] = useMemo(() => {
|
||||
@@ -177,6 +186,32 @@ export default function Rooms({
|
||||
setSelectedRate(undefined)
|
||||
}, [rateSummary, selectedRate])
|
||||
|
||||
useEffect(() => {
|
||||
const pricesWithCurrencies = rooms.roomConfigurations.flatMap((room) =>
|
||||
room.products.map((product) => ({
|
||||
price: product.productType.public.localPrice.pricePerNight,
|
||||
currency: product.productType.public.localPrice.currency,
|
||||
}))
|
||||
)
|
||||
|
||||
const cheapestPrice = pricesWithCurrencies.reduce(
|
||||
(minPrice, { price }) => Math.min(minPrice, price),
|
||||
Infinity
|
||||
)
|
||||
|
||||
const currency = pricesWithCurrencies.find(
|
||||
({ price }) => price === cheapestPrice
|
||||
)?.currency
|
||||
|
||||
trackLowestRoomPrice({
|
||||
hotelId,
|
||||
arrivalDate,
|
||||
departureDate,
|
||||
lowestPrice: cheapestPrice,
|
||||
currency: currency,
|
||||
})
|
||||
}, [arrivalDate, departureDate, hotelId, rooms.roomConfigurations])
|
||||
|
||||
return (
|
||||
<div className={styles.content}>
|
||||
<RoomFilter
|
||||
|
||||
@@ -27,8 +27,8 @@ export default async function TrackingSDK({
|
||||
<RouterTransition
|
||||
pageData={pageData}
|
||||
userData={userTrackingData}
|
||||
// hotelInfo={hotelInfo}
|
||||
//paymentInfo={paymentInfo}
|
||||
hotelInfo={hotelInfo}
|
||||
paymentInfo={paymentInfo}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@
|
||||
"Booking confirmation": "Booking bekræftelse",
|
||||
"Booking number": "Bookingnummer",
|
||||
"Breakfast": "Morgenmad",
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Morgenmad ({totalAdults, plural, one {# voksen} other {# voksne}}) x {totalBreakfasts}",
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}": "Morgenmad ({totalChildren, plural, one {# barn} other {# børn}}) x {totalBreakfasts}",
|
||||
"Breakfast buffet": "Morgenbuffet",
|
||||
"Breakfast charge": "Morgenmadsgebyr",
|
||||
"Breakfast deal can be purchased at the hotel.": "Morgenmad kan købes på hotellet.",
|
||||
@@ -70,8 +72,6 @@
|
||||
"Breakfast is included.": "Morgenmad er inkluderet.",
|
||||
"Breakfast restaurant": "Breakfast restaurant",
|
||||
"Breakfast selection in next step.": "Valg af morgenmad i næste trin.",
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Morgenmad ({totalAdults, plural, one {# voksen} other {# voksne}}) x {totalBreakfasts}",
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}": "Morgenmad ({totalChildren, plural, one {# barn} other {# børn}}) x {totalBreakfasts}",
|
||||
"Bus terminal": "Busstation",
|
||||
"Business": "Forretning",
|
||||
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Ved at acceptere <termsAndConditionsLink>vilkårene og betingelserne for Scandic Friends</termsAndConditionsLink>, forstår jeg, at mine personlige oplysninger vil blive behandlet i overensstemmelse med <privacyPolicy>Scandics privatlivspolitik</privacyPolicy>.",
|
||||
|
||||
@@ -62,6 +62,8 @@
|
||||
"Booking confirmation": "Buchungsbestätigung",
|
||||
"Booking number": "Buchungsnummer",
|
||||
"Breakfast": "Frühstück",
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Frühstück ({totalAdults, plural, one {# erwachsene} other {# erwachsene}}) x {totalBreakfasts}",
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}": "Frühstück ({totalChildren, plural, one {# kind} other {# kinder}}) x {totalBreakfasts}",
|
||||
"Breakfast buffet": "Frühstücksbuffet",
|
||||
"Breakfast charge": "Frühstücksgebühr",
|
||||
"Breakfast deal can be purchased at the hotel.": "Frühstücksangebot kann im Hotel gekauft werden.",
|
||||
@@ -70,8 +72,6 @@
|
||||
"Breakfast is included.": "Frühstück ist inbegriffen.",
|
||||
"Breakfast restaurant": "Breakfast restaurant",
|
||||
"Breakfast selection in next step.": "Frühstücksauswahl in nächsten Schritt.",
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Frühstück ({totalAdults, plural, one {# erwachsene} other {# erwachsene}}) x {totalBreakfasts}",
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}": "Frühstück ({totalChildren, plural, one {# kind} other {# kinder}}) x {totalBreakfasts}",
|
||||
"Business": "Geschäft",
|
||||
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Mit der Annahme der <termsAndConditionsLink>Allgemeinen Geschäftsbedingungen für Scandic Friends</termsAndConditionsLink> erkläre ich mich damit einverstanden, dass meine persönlichen Daten in Übereinstimmung mit der <privacyPolicy>Datenschutzrichtlinie von Scandic verarbeitet werden</privacyPolicy>.",
|
||||
"By paying with any of the payment methods available, I accept the terms for this booking and the general <termsAndConditionsLink>Terms & Conditions</termsAndConditionsLink>, and understand that Scandic will process my personal data for this booking in accordance with <privacyPolicyLink>Scandic's Privacy policy</privacyPolicyLink>. I also accept that Scandic require a valid credit card during my visit in case anything is left unpaid.": "Mit der Zahlung über eine der verfügbaren Zahlungsmethoden akzeptiere ich die Buchungsbedingungen und die allgemeinen <termsAndConditionsLink>Geschäftsbedingungen</termsAndConditionsLink> und verstehe, dass Scandic meine personenbezogenen Daten im Zusammenhang mit dieser Buchung gemäß der <privacyPolicyLink>Scandic Datenschutzrichtlinie</privacyPolicyLink> verarbeitet. Ich akzeptiere, dass Scandic während meines Aufenthalts eine gültige Kreditkarte für eventuelle Rückerstattungen benötigt.",
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
"Booking confirmation": "Booking confirmation",
|
||||
"Booking number": "Booking number",
|
||||
"Breakfast": "Breakfast",
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}",
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}": "Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}",
|
||||
"Breakfast buffet": "Breakfast buffet",
|
||||
"Breakfast charge": "Breakfast charge",
|
||||
"Breakfast deal can be purchased at the hotel.": "Breakfast deal can be purchased at the hotel.",
|
||||
@@ -73,8 +75,6 @@
|
||||
"Breakfast is included.": "Breakfast is included.",
|
||||
"Breakfast restaurant": "Breakfast restaurant",
|
||||
"Breakfast selection in next step.": "Breakfast selection in next step.",
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}",
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}": "Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}",
|
||||
"Bus terminal": "Bus terminal",
|
||||
"Business": "Business",
|
||||
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.",
|
||||
|
||||
@@ -62,16 +62,16 @@
|
||||
"Booking confirmation": "Varausvahvistus",
|
||||
"Booking number": "Varausnumero",
|
||||
"Breakfast": "Aamiainen",
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Aamiainen ({totalAdults, plural, one {# aikuinen} other {# aikuiset}}) x {totalBreakfasts}",
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}": "Aamiainen ({totalChildren, plural, one {# lapsi} other {# lasta}}) x {totalBreakfasts}",
|
||||
"Breakfast buffet": "Aamiaisbuffet",
|
||||
"Breakfast charge": "Aamiaismaksu",
|
||||
"Breakfast deal can be purchased at the hotel.": "Aamiaisdeali voidaan ostaa hotellissa.",
|
||||
"Breakfast excluded": "Aamiainen ei sisälly",
|
||||
"Breakfast included": "Aamiainen sisältyy",
|
||||
"Breakfast is included.": "Aamiainen sisältyy.",
|
||||
"Breakfast restaurant": "Breakfast restaurant",
|
||||
"Breakfast selection in next step.": "Aamiaisvalinta seuraavassa vaiheessa.",
|
||||
"Breakfast charge": "Aamiaismaksu",
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Aamiainen ({totalAdults, plural, one {# aikuinen} other {# aikuiset}}) x {totalBreakfasts}",
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}": "Aamiainen ({totalChildren, plural, one {# lapsi} other {# lasta}}) x {totalBreakfasts}",
|
||||
"Bus terminal": "Bussiasema",
|
||||
"Business": "Business",
|
||||
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Kyllä, <termsAndConditionsLink>hyväksyn Scandic Friends -jäsenyyttä</termsAndConditionsLink> koskevat ehdot ja ymmärrän, että Scandic käsittelee henkilötietojani <privacyPolicy>Scandicin Tietosuojaselosteen mukaisesti</privacyPolicy>.",
|
||||
|
||||
@@ -62,16 +62,16 @@
|
||||
"Booking confirmation": "Bestillingsbekreftelse",
|
||||
"Booking number": "Bestillingsnummer",
|
||||
"Breakfast": "Frokost",
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Frokost ({totalAdults, plural, one {# voksen} other {# voksne}}) x {totalBreakfasts}",
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}": "Frokost ({totalChildren, plural, one {# barn} other {# barn}}) x {totalBreakfasts}",
|
||||
"Breakfast buffet": "Breakfast buffet",
|
||||
"Breakfast charge": "Pris for frokost",
|
||||
"Breakfast deal can be purchased at the hotel.": "Frokostdeal kan kjøpes på hotellet.",
|
||||
"Breakfast excluded": "Frokost ekskludert",
|
||||
"Breakfast included": "Frokost inkludert",
|
||||
"Breakfast is included.": "Frokost er inkludert.",
|
||||
"Breakfast restaurant": "Breakfast restaurant",
|
||||
"Breakfast selection in next step.": "Frokostvalg i neste steg.",
|
||||
"Breakfast charge": "Pris for frokost",
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Frokost ({totalAdults, plural, one {# voksen} other {# voksne}}) x {totalBreakfasts}",
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}": "Frokost ({totalChildren, plural, one {# barn} other {# barn}}) x {totalBreakfasts}",
|
||||
"Bus terminal": "Bussterminal",
|
||||
"Business": "Forretnings",
|
||||
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Ved å akseptere <termsAndConditionsLink>vilkårene og betingelsene for Scandic Friends</termsAndConditionsLink>, er jeg inneforstått med at mine personopplysninger vil bli behandlet i samsvar med <privacyPolicy>Scandics personvernpolicy</privacyPolicy>.",
|
||||
|
||||
@@ -62,16 +62,16 @@
|
||||
"Booking confirmation": "Bokningsbekräftelse",
|
||||
"Booking number": "Bokningsnummer",
|
||||
"Breakfast": "Frukost",
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Frukost ({totalAdults, plural, one {# vuxen} other {# vuxna}}) x {totalBreakfasts}",
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}": "Frukost ({totalChildren, plural, one {# barn} other {# barn}}) x {totalBreakfasts}",
|
||||
"Breakfast buffet": "Frukostbuffé",
|
||||
"Breakfast charge": "Frukostpris",
|
||||
"Breakfast deal can be purchased at the hotel.": "Frukostdeal kan köpas på hotellet.",
|
||||
"Breakfast excluded": "Frukost ingår ej",
|
||||
"Breakfast included": "Frukost ingår",
|
||||
"Breakfast is included.": "Frukost ingår.",
|
||||
"Breakfast restaurant": "Breakfast restaurant",
|
||||
"Breakfast selection in next step.": "Frukostval i nästa steg.",
|
||||
"Breakfast charge": "Frukostpris",
|
||||
"Breakfast ({totalAdults, plural, one {# adult} other {# adults}}) x {totalBreakfasts}": "Frukost ({totalAdults, plural, one {# vuxen} other {# vuxna}}) x {totalBreakfasts}",
|
||||
"Breakfast ({totalChildren, plural, one {# child} other {# children}}) x {totalBreakfasts}": "Frukost ({totalChildren, plural, one {# barn} other {# barn}}) x {totalBreakfasts}",
|
||||
"Bus terminal": "Bussterminal",
|
||||
"Business": "Business",
|
||||
"By accepting the <termsAndConditionsLink>Terms and Conditions for Scandic Friends</termsAndConditionsLink> I understand that my personal data will be processed in accordance with <privacyPolicy>Scandic's Privacy Policy</privacyPolicy>.": "Genom att acceptera <termsAndConditionsLink>villkoren för Scandic Friends</termsAndConditionsLink> förstår jag att mina personuppgifter kommer att behandlas i enlighet med <privacyPolicy>Scandics Integritetspolicy</privacyPolicy>.",
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { create } from "zustand"
|
||||
|
||||
import { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
import { trackOpenSidePeekEvent } from "@/utils/tracking"
|
||||
|
||||
import type { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
|
||||
interface SidePeekState {
|
||||
activeSidePeek: SidePeekEnum | null
|
||||
@@ -26,8 +28,10 @@ const useSidePeekStore = create<SidePeekState>((set) => ({
|
||||
hotelId: null,
|
||||
roomTypeCode: null,
|
||||
showCTA: true,
|
||||
openSidePeek: ({ key, hotelId, roomTypeCode, showCTA }) =>
|
||||
set({ activeSidePeek: key, hotelId, roomTypeCode, showCTA }),
|
||||
openSidePeek: ({ key, hotelId, roomTypeCode, showCTA }) => {
|
||||
trackOpenSidePeekEvent(key, hotelId, window.location.pathname, roomTypeCode)
|
||||
set({ activeSidePeek: key, hotelId, roomTypeCode, showCTA })
|
||||
},
|
||||
closeSidePeek: () =>
|
||||
set({ activeSidePeek: null, hotelId: null, roomTypeCode: null }),
|
||||
}))
|
||||
|
||||
@@ -74,7 +74,7 @@ export type TrackingSDKHotelInfo = {
|
||||
bedTypePosition?: number // Which position the bed type had in the list of available bed types
|
||||
breakfastOption?: string // "no breakfast" or "breakfast buffet"
|
||||
bnr?: string // Booking number
|
||||
analyticsrateCode?: string // flex, save, change
|
||||
analyticsrateCode?: "flex" | "change" | "save" | string
|
||||
specialRoomType?: string // allergy room, pet-friendly, accesibillity room
|
||||
//modifyValues?: string // <price:<value>,roomtype:value>,bed:<value,<breakfast:value>
|
||||
country?: string // Country of the hotel
|
||||
@@ -83,6 +83,18 @@ export type TrackingSDKHotelInfo = {
|
||||
totalPrice?: number
|
||||
lowestRoomPrice?: number
|
||||
searchType?: "destination" | "hotel"
|
||||
ancillaries?: Ancillary[]
|
||||
}
|
||||
|
||||
export type Ancillary = {
|
||||
productId: string
|
||||
productUnits?: number
|
||||
hotelid?: string
|
||||
productPoints: number
|
||||
productPrice: number
|
||||
productType: string
|
||||
productName: string
|
||||
productCategory: string
|
||||
}
|
||||
|
||||
export type TrackingSDKPaymentInfo = {
|
||||
@@ -127,6 +139,14 @@ export type PaymentEvent =
|
||||
| PaymentCancelEvent
|
||||
| PaymentFailEvent
|
||||
|
||||
export type LowestRoomPriceEvent = {
|
||||
hotelId: string | null
|
||||
arrivalDate: string | null
|
||||
departureDate: string | null
|
||||
lowestPrice: number
|
||||
currency?: string
|
||||
}
|
||||
|
||||
// Old tracking setup types:
|
||||
// TODO: Remove this when we delete "current site"
|
||||
export type TrackingProps = {
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import type { SidePeekEnum } from "@/types/components/hotelReservation/sidePeek"
|
||||
import type {
|
||||
LowestRoomPriceEvent,
|
||||
PaymentEvent,
|
||||
PaymentFailEvent,
|
||||
TrackingPosition,
|
||||
@@ -100,6 +102,26 @@ export function trackUpdatePaymentMethod(hotelId: string, method: string) {
|
||||
pushToDataLayer(paymentSelectionEvent)
|
||||
}
|
||||
|
||||
export function trackOpenSidePeekEvent(
|
||||
sidePeek: SidePeekEnum | null,
|
||||
hotelId: string,
|
||||
pathName: string,
|
||||
roomTypeCode?: string | null
|
||||
) {
|
||||
const openSidePeekEvent = {
|
||||
event: "openSidePeek",
|
||||
hotelInfo: {
|
||||
hotelId: hotelId,
|
||||
},
|
||||
cta: {
|
||||
name: sidePeek,
|
||||
roomTypeCode,
|
||||
pathName,
|
||||
},
|
||||
}
|
||||
pushToDataLayer(openSidePeekEvent)
|
||||
}
|
||||
|
||||
export function trackPaymentEvent(paymentEvent: PaymentEvent) {
|
||||
const paymentAttempt = {
|
||||
event: paymentEvent.event,
|
||||
@@ -119,6 +141,22 @@ export function trackPaymentEvent(paymentEvent: PaymentEvent) {
|
||||
pushToDataLayer(paymentAttempt)
|
||||
}
|
||||
|
||||
export function trackLowestRoomPrice(event: LowestRoomPriceEvent) {
|
||||
const lowestRoomPrice = {
|
||||
event: "lowestRoomPrice",
|
||||
hotelInfo: {
|
||||
hotelId: event.hotelId,
|
||||
arrivalDate: event.arrivalDate,
|
||||
departureDate: event.departureDate,
|
||||
},
|
||||
price: {
|
||||
lowestPrice: event.lowestPrice,
|
||||
currency: event.currency,
|
||||
},
|
||||
}
|
||||
pushToDataLayer(lowestRoomPrice)
|
||||
}
|
||||
|
||||
export function pushToDataLayer(data: any) {
|
||||
if (typeof window !== "undefined" && window.adobeDataLayer) {
|
||||
window.adobeDataLayer.push(data)
|
||||
|
||||
Reference in New Issue
Block a user