feat: add tracking events for loyalty pages

This commit is contained in:
Christel Westerberg
2024-07-11 10:12:46 +02:00
parent 127df6ab90
commit a8a67d5e35
7 changed files with 186 additions and 0 deletions

View File

@@ -43,6 +43,9 @@ export default async function RootLayout({
id="Cookiebot"
src="https://consent.cookiebot.com/uc.js"
/>
<Script id="ensure-adobeDataLayer">{`
window.adobeDataLayer = window.adobeDataLayer || []
`}</Script>
<VwoScript />
</head>
<body>

View File

@@ -1,5 +1,6 @@
import { serverClient } from "@/lib/trpc/server"
import TrackingSDK from "@/components/Current/TrackingSDK"
import { Blocks } from "@/components/Loyalty/Blocks"
import Sidebar from "@/components/Loyalty/Sidebar"
import MaxWidth from "@/components/MaxWidth"
@@ -14,6 +15,10 @@ export default async function LoyaltyPage({ lang }: LangParams) {
if (!loyaltyPage) {
return null
}
const loyaltyPageTracking =
await serverClient().contentstack.loyaltyPage.tracking()
return (
<section className={styles.content}>
{loyaltyPage.sidebar.length ? (
@@ -26,6 +31,7 @@ export default async function LoyaltyPage({ lang }: LangParams) {
<Blocks blocks={loyaltyPage.blocks} lang={lang} />
) : null}
</MaxWidth>
<TrackingSDK pageData={loyaltyPageTracking} />
</section>
)
}

View File

@@ -0,0 +1,111 @@
"use client"
import { usePathname } from "next/navigation"
import { useEffect } from "react"
import {
SiteSectionObject,
TrackingSDKData,
TrackingSDKProps,
} from "@/types/components/tracking"
function createSDKPageObject(trackingData: TrackingSDKData) {
const [lang, ...segments] = trackingData.pathName
.split("/")
.filter((seg: string) => seg)
function getSiteSections(segments: string[]): SiteSectionObject {
/*
Adobe expects the properties sitesection1 - sitessection6, hence the for-loop below
The segments ['explore-scandic', 'wifi'] should result in:
{
sitesection1: "explore-scandic",
sitesection2: "explore-scandic|wifi",
sitesection3: "explore-scandic|wifi|",
sitesection4: "explore-scandic|wifi||",
sitesection5: "explore-scandic|wifi|||",
sitesection6: "explore-scandic|wifi||||",
}
*/
const sitesections = {} as SiteSectionObject
for (let i = 0; i < 6; i++) {
const key = ("sitesection" + (i + 1)) as keyof SiteSectionObject
sitesections[key] = segments.slice(0, i + 1).join("|")
if (i > 0 && !segments[i]) {
sitesections[key] = sitesections[key].concat(
"|".repeat(i + 1 - segments.length)
)
}
}
return sitesections
}
const siteSections = getSiteSections(segments)
const { host: domain } = window.location
const page_obj = {
event: "pageView",
pageInfo: {
pageName: segments.join("|"),
pageType: "contentpage",
pageId: trackingData.pageId,
channel: "",
siteSections,
domain,
siteversion: "new-web",
domainlanguage: trackingData.lang ? trackingData.lang : lang,
createDate: trackingData.createdDate,
publishDate: trackingData.publishedDate,
// sessionid: "<unique identifier of session>", // base on what?
},
}
return page_obj
}
export default function TrackingSDK({ pageData }: TrackingSDKProps) {
const pathName = usePathname()
function CookiebotCallbackOnAccept() {
const cookie = window._satellite.cookie.get("CookieConsent")
if (window.Cookiebot?.changed && window.adobe) {
if (cookie?.includes("statistics:true")) {
window.adobe.optIn.approve(window.adobe.OptInCategories.ANALYTICS, true)
} else {
window.adobe.optIn.deny(window.adobe.OptInCategories.ANALYTICS, true)
}
window.adobe.optIn.complete()
console.warn("window.load event explicitly dispatched.")
window.dispatchEvent(new Event("load"))
}
}
function CookebotCallbackOnDecline() {
if (window.Cookiebot?.changed && window.adobe) {
window.adobe.optIn.deny(window.adobe.OptInCategories.ANALYTICS, true)
}
}
useEffect(() => {
if (window.adobeDataLayer) {
const trackingData = { ...pageData, pathName }
const pageObject = createSDKPageObject(trackingData)
window.adobeDataLayer.push(pageObject)
}
}, [pathName, pageData])
useEffect(() => {
// handle consent
window.addEventListener("CookiebotOnAccept", CookiebotCallbackOnAccept)
window.addEventListener("CookiebotOnDecline", CookebotCallbackOnDecline)
return () => {
window.removeEventListener("CookiebotOnAccept", CookiebotCallbackOnAccept)
window.removeEventListener(
"CookiebotOnDecline",
CookebotCallbackOnDecline
)
}
}, [])
return null
}

View File

@@ -362,3 +362,14 @@ query GetFiNoSvUrlsLoyaltyPage($uid: String!) {
}
}
}
query GetTrackingLoyaltyPage($locale: String!, $uid: String!) {
loyalty_page(locale: $locale, uid: $uid) {
system {
locale
created_at
uid
updated_at
}
}
}

View File

@@ -1,6 +1,7 @@
import {
GetLoyaltyPage,
GetLoyaltyPageRefs,
GetTrackingLoyaltyPage,
} from "@/lib/graphql/Query/LoyaltyPage.graphql"
import { request } from "@/lib/graphql/request"
import { notFound } from "@/server/errors/trpc"
@@ -29,6 +30,10 @@ import {
LoyaltyCardsGridEnum,
SidebarTypenameEnum,
} from "@/types/components/loyalty/enums"
import {
TrackingChannelEnum,
TrackingSDKPageData,
} from "@/types/components/tracking"
function makeImageVaultImage(image: any) {
return image && !!Object.keys(image).length
@@ -224,4 +229,26 @@ export const loyaltyPageQueryRouter = router({
// Assert LoyaltyPage type to get correct typings for RTE fields
return validatedLoyaltyPage.data as LoyaltyPage
}),
tracking: contentstackExtendedProcedureUID.query(async ({ ctx }) => {
const { lang, uid } = ctx
const response = await request<any>(GetTrackingLoyaltyPage, {
locale: lang,
uid,
})
if (!response.data) {
throw notFound(response)
}
const loyaltyTrackingData: TrackingSDKPageData = {
pageId: response.data.loyalty_page.system.uid,
lang: response.data.loyalty_page.system.locale,
publishedDate: response.data.loyalty_page.system.published_at,
createdDate: response.data.loyalty_page.system.created_at,
channel: TrackingChannelEnum["scandic-friends"],
}
return loyaltyTrackingData
}),
})

View File

@@ -1,5 +1,32 @@
import type { Lang } from "@/constants/languages"
export enum TrackingChannelEnum {
"scandic-friends" = "scandic-friends",
}
export type TrackingChannel = keyof typeof TrackingChannelEnum
export type TrackingSDKPageData = {
pageId: string
createdDate: string
publishedDate: string
lang: Lang
channel: TrackingChannel
}
export type TrackingSDKProps = {
pageData: TrackingSDKPageData
}
export type TrackingSDKData = {
lang: Lang
pathName: string
pageId: string
publishedDate: string
createdDate: string
}
// Old tracking setup types:
export type TrackingProps = {
pageData: {
pageId: string

1
types/window.d.ts vendored
View File

@@ -1,5 +1,6 @@
interface Window {
datalayer: { [key: string]: any }
adobeDataLayer: any[]
_satellite: { cookie: { get: (s: string) => string } }
adobe: {
OptInCategories: { ANALYTICS: string }