diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/details/page.tsx b/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/details/page.tsx
index 37311010a..bd81ddfa7 100644
--- a/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/details/page.tsx
+++ b/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/details/page.tsx
@@ -96,7 +96,7 @@ export default async function DetailsPage({
hotel.merchantInformationData.alternatePaymentOptions = []
}
- const { hotelsTrackingData, pageTrackingData } = getTracking(
+ const { hotelsTrackingData, pageTrackingData, ancillaries } = getTracking(
booking,
hotel,
rooms,
@@ -170,7 +170,11 @@ export default async function DetailsPage({
-
+
)
}
diff --git a/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/details/tracking.ts b/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/details/tracking.ts
index ebeef6b18..6eb4719d0 100644
--- a/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/details/tracking.ts
+++ b/apps/scandic-web/app/[lang]/(live)/(public)/hotelreservation/(standard)/details/tracking.ts
@@ -2,18 +2,25 @@ import { differenceInCalendarDays, format, isWeekend } from "date-fns"
import { REDEMPTION } from "@/constants/booking"
+import { sumPackages } from "@/components/HotelReservation/utils"
import { getSpecialRoomType } from "@/utils/specialRoomType"
import { ChildBedMapEnum } from "@/types/components/bookingWidget/enums"
+import { RoomPackageCodeEnum } from "@/types/components/hotelReservation/selectRate/roomFilter"
import type { SelectRateSearchParams } from "@/types/components/hotelReservation/selectRate/selectRate"
import {
TrackingChannelEnum,
+ type TrackingSDKAncillaries,
type TrackingSDKHotelInfo,
type TrackingSDKPageData,
} from "@/types/components/tracking"
import { CurrencyEnum } from "@/types/enums/currency"
import type { Hotel } from "@/types/hotel"
import type { Room } from "@/types/providers/details/room"
+import type {
+ PriceProduct,
+ Product,
+} from "@/types/trpc/routers/hotel/roomAvailability"
import type { Lang } from "@/constants/languages"
import type { SelectHotelParams } from "@/utils/url"
@@ -47,6 +54,10 @@ export function getTracking(
.join("|"),
analyticsRateCode: rooms.map((room) => room.rate).join("|"),
arrivalDate: format(arrivalDate, "yyyy-MM-dd"),
+ // only include bedtype here if it is "preselected" meanining there is only 1
+ bedType: rooms
+ .map((r) => (r?.bedTypes?.length === 1 ? r.bedTypes[0].description : "-"))
+ .join("|"),
// Comma separated booking code values in "code,code,n/a" format for multiroom and "code" or "n/a" for singleroom
// n/a is used whenever code is Not applicable as defined by Tracking team
bookingCode: rooms
@@ -72,6 +83,22 @@ export function getTracking(
.join("|"),
country: hotel?.address.country,
departureDate: format(departureDate, "yyyy-MM-dd"),
+ discount: rooms
+ .map((room, idx) => {
+ const isMainRoom = idx === 0
+ if (
+ hasMemberPrice(room.roomRate) &&
+ isMainRoom &&
+ isMember &&
+ hasPublicPrice(room.roomRate)
+ ) {
+ const memberPrice = room.roomRate.member.localPrice.pricePerStay
+ const publicPrice = room.roomRate.public.localPrice.pricePerStay
+ return publicPrice - memberPrice
+ }
+ return 0
+ })
+ .join(","),
duration: differenceInCalendarDays(departureDate, arrivalDate),
hotelID: hotel?.operaId,
leadTime: differenceInCalendarDays(arrivalDate, new Date()),
@@ -80,17 +107,28 @@ export function getTracking(
.map((room) => room.childrenInRoom?.length ?? 0)
.join(","),
noOfRooms: booking.rooms.length,
+ ...(rooms.length > 1 && {
+ multiroomRateIdentity: rooms.every((room) => {
+ const firstRoom = rooms[0]
+ if (
+ hasPublicPrice(firstRoom.roomRate) &&
+ hasPublicPrice(room.roomRate)
+ ) {
+ return (
+ firstRoom.roomRate.public?.localPrice.pricePerNight ===
+ room.roomRate.public?.localPrice.pricePerNight
+ )
+ }
+ })
+ ? "same rate"
+ : "mixed rate",
+ }),
rateCode: rooms
.map((room, idx) => {
const isMainRoom = idx === 0
- if (
- "member" in room.roomRate &&
- room.roomRate.member &&
- isMember &&
- isMainRoom
- ) {
+ if (hasMemberPrice(room.roomRate) && isMember && isMainRoom) {
return room.roomRate.member.rateCode
- } else if ("public" in room.roomRate && room.roomRate.public) {
+ } else if (hasPublicPrice(room.roomRate)) {
return room.roomRate.public.rateCode
} else if ("corporateCheque" in room.roomRate) {
return room.roomRate.corporateCheque.rateCode
@@ -108,25 +146,29 @@ export function getTracking(
rateCodeName: rooms.map((room) => room.rateDefinitionTitle).join(","),
rateCodeType: rooms.map((room) => room.rateType.toLowerCase()).join(","),
region: hotel?.address.city,
- revenueCurrencyCode: rooms
- .map((room) => {
- if ("corporateCheque" in room.roomRate) {
- return CurrencyEnum.CC
- } else if ("redemption" in room.roomRate) {
- return CurrencyEnum.POINTS
- } else if ("voucher" in room.roomRate) {
- return CurrencyEnum.Voucher
- } else if ("public" in room.roomRate && room.roomRate.public) {
- return room.roomRate.public.localPrice.currency
- } else if ("member" in room.roomRate && room.roomRate.member) {
- return room.roomRate.member.localPrice.currency
- }
- return CurrencyEnum.Unknown
- })
- .join(","),
+ revenueCurrencyCode: [
+ ...new Set(
+ rooms.map((room) => {
+ if ("corporateCheque" in room.roomRate) {
+ return CurrencyEnum.CC
+ } else if ("redemption" in room.roomRate) {
+ return CurrencyEnum.POINTS
+ } else if ("voucher" in room.roomRate) {
+ return CurrencyEnum.Voucher
+ } else if (hasPublicPrice(room.roomRate)) {
+ return room.roomRate.public.localPrice.currency
+ } else if (hasMemberPrice(room.roomRate)) {
+ return room.roomRate.member.localPrice.currency
+ }
+ return CurrencyEnum.Unknown
+ })
+ ),
+ ].join(","),
rewardNight: booking.searchType === REDEMPTION ? "yes" : "no",
rewardNightAvailability:
booking.searchType === REDEMPTION ? "true" : "false",
+ roomPrice: calcTotalRoomPrice(rooms, isMember),
+ totalPrice: calcTotalPrice(rooms, isMember),
searchTerm: city,
searchType: "hotel",
specialRoomType: rooms
@@ -134,8 +176,91 @@ export function getTracking(
.join(","),
}
+ const roomsWithPetRoom = rooms.filter(hasPetRoom)
+ const ancillaries: TrackingSDKAncillaries = roomsWithPetRoom
+ .slice(0, 1) // should only be one item
+ .map((room) => {
+ const petRoomPackage = room.packages.find(
+ (p) => p.code === RoomPackageCodeEnum.PET_ROOM
+ )
+ return {
+ hotelId: hotel.operaId,
+ productId: petRoomPackage?.code!, // property is guaranteed at this point
+ productUnits: roomsWithPetRoom.length,
+ productPoints: 0,
+ productPrice: petRoomPackage?.localPrice.totalPrice ?? 0,
+ productType: "room preference",
+ productName: "pet room",
+ productCategory: "",
+ }
+ })
+
return {
hotelsTrackingData,
pageTrackingData,
+ ancillaries,
}
}
+
+function hasPublicPrice(
+ roomRate: Product
+): roomRate is PriceProduct & { public: NonNullable } {
+ if ("public" in roomRate && roomRate.public) {
+ return true
+ }
+ return false
+}
+
+function hasMemberPrice(
+ roomRate: Product
+): roomRate is PriceProduct & { member: NonNullable } {
+ if ("member" in roomRate && roomRate.member) {
+ return true
+ }
+ return false
+}
+
+function hasPetRoom(
+ room: Room
+): room is Room & { packages: NonNullable } {
+ if (!room.packages) {
+ return false
+ }
+ return room.packages.some((p) => p.code === RoomPackageCodeEnum.PET_ROOM)
+}
+
+function calcTotalPrice(rooms: Room[], isMember: boolean) {
+ const totalRoomPrice = calcTotalRoomPrice(rooms, isMember)
+ const totalPackageSum = rooms.reduce((total, room) => {
+ const packageSum = sumPackages(room.packages)
+ return (total += packageSum.price ?? 0)
+ }, 0)
+
+ return totalRoomPrice + totalPackageSum
+}
+
+function calcTotalRoomPrice(rooms: Room[], isMember: boolean) {
+ return rooms.reduce((total, room, idx) => {
+ // When it comes special rates, only redemption has additional price and that should be added
+ // other special rates like voucher, corporateCheck should be added as 0 according to Priyanka
+ if ("redemption" in room.roomRate) {
+ return (
+ room.roomRate.redemption.requestedPrice?.additionalPricePerStay ?? 0
+ )
+ } else if (
+ "corporateCheck" in room.roomRate ||
+ "voucher" in room.roomRate
+ ) {
+ return 0
+ }
+
+ const isMainRoom = idx === 0
+ if (hasMemberPrice(room.roomRate) && isMember && isMainRoom) {
+ total += room.roomRate.member.localPrice.pricePerStay
+ } else if (hasPublicPrice(room.roomRate)) {
+ total += room.roomRate.public.localPrice.pricePerStay
+ }
+
+ return total
+ }, 0)
+}
diff --git a/apps/scandic-web/components/HotelReservation/BookingConfirmation/Tracking/tracking.ts b/apps/scandic-web/components/HotelReservation/BookingConfirmation/Tracking/tracking.ts
index 4333eee13..00f016ef8 100644
--- a/apps/scandic-web/components/HotelReservation/BookingConfirmation/Tracking/tracking.ts
+++ b/apps/scandic-web/components/HotelReservation/BookingConfirmation/Tracking/tracking.ts
@@ -146,17 +146,19 @@ export function getTracking(
.toLowerCase(),
//rateCodeType: , //TODO: Add when available in API. "regular, promotion, corporate etx",
region: hotel?.address.city,
- revenueCurrencyCode: rooms.map((r) => r.currencyCode).join(","),
+ revenueCurrencyCode: [...new Set(rooms.map((r) => r.currencyCode))].join(
+ ","
+ ),
rewardNight: booking.roomPoints > 0 ? "yes" : "no",
rewardNightAvailability: booking.roomPoints > 0 ? "true" : "false",
points: booking.roomPoints > 0 ? booking.roomPoints : undefined,
- roomPrice: rooms.map((r) => r.roomPrice).join(","),
+ roomPrice: rooms.reduce((total, room) => total + room.roomPrice, 0),
roomTypeCode: rooms.map((r) => r.roomTypeCode ?? "-").join(","),
searchType: "hotel",
specialRoomType: rooms
.map((room) => getSpecialRoomType(room.packages))
.join(","),
- totalPrice: rooms.map((r) => r.totalPrice).join(","),
+ totalPrice: rooms.reduce((total, room) => total + room.totalPrice, 0),
lateArrivalGuarantee: booking.rateDefinition.mustBeGuaranteed
? "mandatory"
: isFlexBooking
diff --git a/apps/scandic-web/types/components/tracking.ts b/apps/scandic-web/types/components/tracking.ts
index 47eea8b05..c89dc9341 100644
--- a/apps/scandic-web/types/components/tracking.ts
+++ b/apps/scandic-web/types/components/tracking.ts
@@ -70,11 +70,12 @@ export type TrackingSDKHotelInfo = {
childBedPreference?: string
country?: string // Country of the hotel
departureDate?: string
- discount?: number
+ discount?: number | string
duration?: number // Number of nights to stay
hotelID?: string
leadTime?: number // Number of days from booking date until arrivalDate
lowestRoomPrice?: number
+ multiroomRateIdentity?: string
//modifyValues?: string // ,roomtype:value>,bed:
noOfAdults?: number | string // multiroom support, "2,1,3"
noOfChildren?: number | string // multiroom support, "2,1,3"