feat: add tracking events for loyalty pages
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
111
components/Current/TrackingSDK.tsx
Normal file
111
components/Current/TrackingSDK.tsx
Normal 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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -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
1
types/window.d.ts
vendored
@@ -1,5 +1,6 @@
|
||||
interface Window {
|
||||
datalayer: { [key: string]: any }
|
||||
adobeDataLayer: any[]
|
||||
_satellite: { cookie: { get: (s: string) => string } }
|
||||
adobe: {
|
||||
OptInCategories: { ANALYTICS: string }
|
||||
|
||||
Reference in New Issue
Block a user