This commit is contained in:
Linus Flood
2024-10-03 15:16:56 +02:00
parent b047e31990
commit e29dff1874
10 changed files with 77 additions and 87 deletions

View File

@@ -7,10 +7,13 @@ import { env } from "@/env/server"
import TrpcProvider from "@/lib/trpc/Provider" import TrpcProvider from "@/lib/trpc/Provider"
import TokenRefresher from "@/components/Auth/TokenRefresher" import TokenRefresher from "@/components/Auth/TokenRefresher"
import CookieBotConsent from "@/components/CookieBot"
import AdobeSDKScript from "@/components/Current/AdobeSDKScript" import AdobeSDKScript from "@/components/Current/AdobeSDKScript"
import GTMScript from "@/components/Current/GTMScript"
import VwoScript from "@/components/Current/VwoScript" import VwoScript from "@/components/Current/VwoScript"
import { ToastHandler } from "@/components/TempDesignSystem/Toasts" import { ToastHandler } from "@/components/TempDesignSystem/Toasts"
import { preloadUserTracking } from "@/components/TrackingSDK" import { preloadUserTracking } from "@/components/TrackingSDK"
import RouterTracking from "@/components/TrackingSDK/RouterTracking"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import ServerIntlProvider from "@/i18n/Provider" import ServerIntlProvider from "@/i18n/Provider"
import { setLang } from "@/i18n/serverContext" import { setLang } from "@/i18n/serverContext"
@@ -38,6 +41,7 @@ export default async function RootLayout({
<html lang={params.lang}> <html lang={params.lang}>
<head> <head>
<AdobeSDKScript /> <AdobeSDKScript />
<GTMScript />
<Script data-cookieconsent="ignore" src="/_static/js/cookie-bot.js" /> <Script data-cookieconsent="ignore" src="/_static/js/cookie-bot.js" />
<Script <Script
strategy="beforeInteractive" strategy="beforeInteractive"
@@ -55,12 +59,15 @@ export default async function RootLayout({
<body> <body>
<ServerIntlProvider intl={{ defaultLocale, locale, messages }}> <ServerIntlProvider intl={{ defaultLocale, locale, messages }}>
<TrpcProvider> <TrpcProvider>
{header} <RouterTracking>
{!env.HIDE_FOR_NEXT_RELEASE && <>{bookingwidget}</>} {header}
{children} {!env.HIDE_FOR_NEXT_RELEASE && <>{bookingwidget}</>}
{footer} {children}
{footer}
</RouterTracking>
<ToastHandler /> <ToastHandler />
<TokenRefresher /> <TokenRefresher />
<CookieBotConsent />
</TrpcProvider> </TrpcProvider>
</ServerIntlProvider> </ServerIntlProvider>
</body> </body>

View File

@@ -5,6 +5,7 @@ import Script from "next/script"
import TokenRefresher from "@/components/Auth/TokenRefresher" import TokenRefresher from "@/components/Auth/TokenRefresher"
import BookingWidget from "@/components/BookingWidget" import BookingWidget from "@/components/BookingWidget"
import CookieBotConsent from "@/components/CookieBot"
import AdobeScript from "@/components/Current/AdobeScript" import AdobeScript from "@/components/Current/AdobeScript"
import Footer from "@/components/Current/Footer" import Footer from "@/components/Current/Footer"
import LangPopup from "@/components/Current/LangPopup" import LangPopup from "@/components/Current/LangPopup"
@@ -69,6 +70,7 @@ export default async function RootLayout({
{children} {children}
<Footer /> <Footer />
<TokenRefresher /> <TokenRefresher />
<CookieBotConsent />
</ServerIntlProvider> </ServerIntlProvider>
<Script id="page-tracking">{` <Script id="page-tracking">{`
typeof _satellite !== "undefined" && _satellite.pageBottom(); typeof _satellite !== "undefined" && _satellite.pageBottom();

View File

@@ -6,6 +6,7 @@ import Script from "next/script"
import TrpcProvider from "@/lib/trpc/Provider" import TrpcProvider from "@/lib/trpc/Provider"
import AdobeSDKScript from "@/components/Current/AdobeSDKScript" import AdobeSDKScript from "@/components/Current/AdobeSDKScript"
import GTMScript from "@/components/Current/GTMScript"
import { getIntl } from "@/i18n" import { getIntl } from "@/i18n"
import ServerIntlProvider from "@/i18n/Provider" import ServerIntlProvider from "@/i18n/Provider"
import { setLang } from "@/i18n/serverContext" import { setLang } from "@/i18n/serverContext"
@@ -31,6 +32,7 @@ export default async function RootLayout({
<html lang={params.lang}> <html lang={params.lang}>
<head> <head>
<AdobeSDKScript /> <AdobeSDKScript />
<GTMScript />
<Script id="ensure-adobeDataLayer">{` <Script id="ensure-adobeDataLayer">{`
window.adobeDataLayer = window.adobeDataLayer || [] window.adobeDataLayer = window.adobeDataLayer || []
`}</Script> `}</Script>

View File

@@ -1,24 +1,13 @@
"use client" "use client"
import { usePathname } from "next/navigation" import { usePathname } from "next/navigation"
import { useCallback, useEffect, useRef } from "react" import { useCallback, useEffect } from "react"
import { webviews } from "@/constants/routes/webviews" import { webviews } from "@/constants/routes/webviews"
import useTrackingStore from "@/stores/tracking"
import { createSDKPageObject } from "@/utils/tracking" export default function CookieBot() {
import { TrackingSDKProps } from "@/types/components/tracking"
export default function TrackingSDK({
pageData,
userData,
hotelInfo,
}: TrackingSDKProps) {
const pathName = usePathname() const pathName = usePathname()
const isWebview = webviews.includes(pathName) const isWebview = webviews.includes(pathName)
const { hasRun, setHasRun, getPageLoadTime } = useTrackingStore()
const hasRunLocal = useRef<boolean>(false)
const CookiebotCallbackOnAccept = useCallback(() => { const CookiebotCallbackOnAccept = useCallback(() => {
const cookie = window._satellite.cookie.get("CookieConsent") const cookie = window._satellite.cookie.get("CookieConsent")
@@ -43,38 +32,6 @@ export default function TrackingSDK({
} }
} }
useEffect(() => {
if (!hasRun && !hasRunLocal.current) {
hasRunLocal.current = true
setHasRun()
if (window.adobeDataLayer) {
const trackingData = {
...pageData,
pathName,
pageLoadTime: getPageLoadTime(),
}
const pageObject = createSDKPageObject(trackingData)
console.log("TRACKING: Tracking pageView", pageObject, userData)
window.adobeDataLayer.push({
event: "pageView",
pageInfo: pageObject,
userInfo: userData,
hotelInfo: hotelInfo,
})
}
}
}, [
pathName,
pageData,
userData,
hasRun,
setHasRun,
hotelInfo,
getPageLoadTime,
])
useEffect(() => { useEffect(() => {
// handle consent // handle consent
window.addEventListener("CookiebotOnAccept", CookiebotCallbackOnAccept) window.addEventListener("CookiebotOnAccept", CookiebotCallbackOnAccept)

View File

@@ -0,0 +1,21 @@
export default function GTMScript() {
return (
<script
data-cookieconsent="statistics"
dangerouslySetInnerHTML={{
__html: `
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://analytics.scandichotels.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','adobeDataLayer','GTM-KNJCW67W');
`,
}}
async
/>
)
}

View File

@@ -3,10 +3,7 @@ import NextLink from "next/link"
import { usePathname, useRouter } from "next/navigation" import { usePathname, useRouter } from "next/navigation"
import { startTransition, useCallback } from "react" import { startTransition, useCallback } from "react"
import useRouterTransitionStore from "@/stores/router-transition" import { trackClick } from "@/utils/tracking"
import useTrackingStore from "@/stores/tracking"
import { trackClick, trackPageViewStart } from "@/utils/tracking"
import { linkVariants } from "./variants" import { linkVariants } from "./variants"
@@ -28,7 +25,6 @@ export default function Link({
...props ...props
}: LinkProps) { }: LinkProps) {
const currentPageSlug = usePathname() const currentPageSlug = usePathname()
const { setInitialPageLoadTime } = useTrackingStore()
let isActive = active || currentPageSlug === href let isActive = active || currentPageSlug === href
if (partialMatch && !isActive) { if (partialMatch && !isActive) {
@@ -46,10 +42,6 @@ export default function Link({
const router = useRouter() const router = useRouter()
const startRouterTransition = useRouterTransitionStore(
(state) => state.startRouterTransition
)
const trackClickById = useCallback(() => { const trackClickById = useCallback(() => {
if (trackingId) { if (trackingId) {
trackClick(trackingId) trackClick(trackingId)
@@ -74,10 +66,7 @@ export default function Link({
return return
} }
e.preventDefault() e.preventDefault()
setInitialPageLoadTime(Date.now())
trackPageViewStart()
startTransition(() => { startTransition(() => {
startRouterTransition()
router.push(href, { scroll }) router.push(href, { scroll })
}) })
}} }}

View File

@@ -0,0 +1,27 @@
"use client"
import { usePathname, useSearchParams } from "next/navigation"
import { startTransition, useEffect } from "react"
import useRouterTransitionStore from "@/stores/router-transition"
import useTrackingStore from "@/stores/tracking"
import { trackPageViewStart } from "@/utils/tracking"
export default function RouterTracking({ children }: React.PropsWithChildren) {
const pathName = usePathname()
const searchParams = useSearchParams()
const { setInitialPageLoadTime } = useTrackingStore()
const { startRouterTransition } = useRouterTransitionStore()
useEffect(() => {
setInitialPageLoadTime(Date.now())
trackPageViewStart()
startTransition(() => {
startRouterTransition()
})
}, [pathName, searchParams, setInitialPageLoadTime, startRouterTransition])
return <>{children}</>
}

View File

@@ -6,7 +6,7 @@ import { startTransition, useEffect, useOptimistic, useState } from "react"
import useRouterTransitionStore from "@/stores/router-transition" import useRouterTransitionStore from "@/stores/router-transition"
import useTrackingStore from "@/stores/tracking" import useTrackingStore from "@/stores/tracking"
import { createSDKPageObject, trackPageViewStart } from "@/utils/tracking" import { createSDKPageObject } from "@/utils/tracking"
import { TrackingSDKProps } from "@/types/components/tracking" import { TrackingSDKProps } from "@/types/components/tracking"
@@ -32,17 +32,6 @@ export default function RouterTransition({
const pathName = usePathname() const pathName = usePathname()
const { isTransitioning, stopRouterTransition } = useRouterTransitionStore() const { isTransitioning, stopRouterTransition } = useRouterTransitionStore()
// useEffect(() => {
// const handleStart = () => {
// trackPageViewStart()
// setInitialPageLoadTime(Date.now())
// }
// return () => {
// handleStart()
// }
// }, [pathName])
useEffect(() => { useEffect(() => {
if (isTransitioning && status === TransitionStatusEnum.NotRun) { if (isTransitioning && status === TransitionStatusEnum.NotRun) {
startTransition(() => { startTransition(() => {

View File

@@ -2,8 +2,6 @@ import { serverClient } from "@/lib/trpc/server"
import RouterTransition from "@/components/TrackingSDK/RouterTransition" import RouterTransition from "@/components/TrackingSDK/RouterTransition"
import TrackingSDKClient from "./Client"
import { import {
TrackingSDKHotelInfo, TrackingSDKHotelInfo,
TrackingSDKPageData, TrackingSDKPageData,
@@ -23,17 +21,10 @@ export default async function TrackingSDK({
const userTrackingData = await serverClient().user.tracking() const userTrackingData = await serverClient().user.tracking()
return ( return (
<> <RouterTransition
<TrackingSDKClient pageData={pageData}
pageData={pageData} userData={userTrackingData}
userData={userTrackingData} hotelInfo={hotelInfo}
hotelInfo={hotelInfo} />
/>
<RouterTransition
pageData={pageData}
userData={userTrackingData}
hotelInfo={hotelInfo}
/>
</>
) )
} }

View File

@@ -74,6 +74,11 @@ export type TrackingSDKHotelInfo = {
analyticsrateCode?: string // flex, save, change analyticsrateCode?: string // flex, save, change
specialRoomType?: string // allergy room, pet-friendly, accesibillity room specialRoomType?: string // allergy room, pet-friendly, accesibillity room
//modifyValues?: string // <price:<value>,roomtype:value>,bed:<value,<breakfast:value> //modifyValues?: string // <price:<value>,roomtype:value>,bed:<value,<breakfast:value>
country?: string // Country of the hotel
region?: string // Region of the hotel
discount?: number
totalPrice?: number
lowestRoomPrice?: number
} }
export type TrackingSDKProps = { export type TrackingSDKProps = {