From 4c9205d9f4a195d4c2f1b65d00fd8c5e9b322d93 Mon Sep 17 00:00:00 2001 From: Christel Westerberg Date: Tue, 20 Aug 2024 08:59:18 +0200 Subject: [PATCH 1/6] wip fix: make sure loginType and ECID is trackable from webviews --- components/TempDesignSystem/Link/index.tsx | 26 +++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/components/TempDesignSystem/Link/index.tsx b/components/TempDesignSystem/Link/index.tsx index 1a2e46415..832d5a608 100644 --- a/components/TempDesignSystem/Link/index.tsx +++ b/components/TempDesignSystem/Link/index.tsx @@ -1,9 +1,9 @@ "use client" import NextLink from "next/link" -import { usePathname } from "next/navigation" -import { useCallback, useEffect } from "react" +import { usePathname, useRouter } from "next/navigation" +import { useCallback, useEffect, useTransition } from "react" -import { trackClick } from "@/utils/tracking" +import { trackClick, trackPageViewStart } from "@/utils/tracking" import { linkVariants } from "./variants" @@ -39,6 +39,9 @@ export default function Link({ variant, }) + const [isPending, startTransition] = useTransition() + const router = useRouter() + const trackClickById = useCallback(() => { if (trackingId) { trackClick(trackingId) @@ -56,11 +59,28 @@ export default function Link({ } }, [trackClickById, trackingId]) + useEffect(() => { + if (!isPending) { + console.log("PENDING IS DONE") + } + }, [isPending]) + return ( { + trackPageViewStart() + + startTransition(() => { + router.push(href) + console.log({ isPending }) + if (!isPending) { + console.log("Not pending anymore!") + } + }) + }} href={href} id={trackingId} {...props} From f868025a9dda04de5d2fddc7b0a9b7ad6a61718b Mon Sep 17 00:00:00 2001 From: Christel Westerberg Date: Wed, 21 Aug 2024 11:11:15 +0200 Subject: [PATCH 2/6] fix: ad events for tracking navigations and initial page load --- components/TempDesignSystem/Link/index.tsx | 23 +++---- components/TrackingSDK/Client.tsx | 74 ++++++++++++++++----- components/TrackingSDK/RouterTransition.tsx | 33 +++++++++ components/TrackingSDK/index.tsx | 9 ++- stores/router-transition.ts | 21 ++++++ 5 files changed, 129 insertions(+), 31 deletions(-) create mode 100644 components/TrackingSDK/RouterTransition.tsx create mode 100644 stores/router-transition.ts diff --git a/components/TempDesignSystem/Link/index.tsx b/components/TempDesignSystem/Link/index.tsx index 832d5a608..8ef549d71 100644 --- a/components/TempDesignSystem/Link/index.tsx +++ b/components/TempDesignSystem/Link/index.tsx @@ -1,7 +1,9 @@ "use client" import NextLink from "next/link" import { usePathname, useRouter } from "next/navigation" -import { useCallback, useEffect, useTransition } from "react" +import { startTransition, useCallback, useEffect } from "react" + +import useRouterTransitionStore from "@/stores/router-transition" import { trackClick, trackPageViewStart } from "@/utils/tracking" @@ -39,9 +41,12 @@ export default function Link({ variant, }) - const [isPending, startTransition] = useTransition() const router = useRouter() + const startRouterTransition = useRouterTransitionStore( + (state) => state.startRouterTransition + ) + const trackClickById = useCallback(() => { if (trackingId) { trackClick(trackingId) @@ -59,26 +64,16 @@ export default function Link({ } }, [trackClickById, trackingId]) - useEffect(() => { - if (!isPending) { - console.log("PENDING IS DONE") - } - }, [isPending]) - return ( { - trackPageViewStart() - startTransition(() => { + trackPageViewStart() + startRouterTransition() router.push(href) - console.log({ isPending }) - if (!isPending) { - console.log("Not pending anymore!") - } }) }} href={href} diff --git a/components/TrackingSDK/Client.tsx b/components/TrackingSDK/Client.tsx index 95d42884c..850384f1a 100644 --- a/components/TrackingSDK/Client.tsx +++ b/components/TrackingSDK/Client.tsx @@ -1,7 +1,7 @@ "use client" import { usePathname } from "next/navigation" -import { useCallback, useEffect } from "react" +import { useCallback, useEffect, useState } from "react" import { webviews } from "@/constants/routes/webviews" @@ -16,20 +16,17 @@ function createSDKPageObject(trackingData: TrackingSDKData) { const { host: domain } = window.location const page_obj = { - event: "pageView", - pageInfo: { - pageType: trackingData.pageType, - pageName: joinedSegments, - pageId: trackingData.pageId, - channel: trackingData.channel, - siteSection: joinedSegments, - domain, - siteversion: "new-web", - domainlanguage: trackingData.lang ? trackingData.lang : lang, - createDate: trackingData.createdDate, - publishDate: trackingData.publishedDate, - // sessionid: "", // base on what? - }, + pageType: trackingData.pageType, + pageName: joinedSegments, + pageId: trackingData.pageId, + channel: trackingData.channel, + siteSection: joinedSegments, + domain, + siteversion: "new-web", + domainlanguage: trackingData.lang ? trackingData.lang : lang, + createDate: trackingData.createdDate, + publishDate: trackingData.publishedDate, + // sessionid: "", // base on what? } return page_obj } @@ -37,6 +34,7 @@ function createSDKPageObject(trackingData: TrackingSDKData) { export default function TrackingSDK({ pageData, userData }: TrackingSDKProps) { const pathName = usePathname() const isWebview = webviews.includes(pathName) + const [initPerformanceTracking, setInitPerformanceTracking] = useState(false) const CookiebotCallbackOnAccept = useCallback(() => { const cookie = window._satellite.cookie.get("CookieConsent") @@ -62,11 +60,55 @@ export default function TrackingSDK({ pageData, userData }: TrackingSDKProps) { } } + useEffect(() => { + if (initPerformanceTracking) { + const perfObserver = new PerformanceObserver((observedEntries) => { + const entry = observedEntries.getEntriesByType("navigation")[0] + + if (entry && window.adobeDataLayer) { + const trackingData = { ...pageData, pathName } + const pageObject = createSDKPageObject(trackingData) + + const { loadEventEnd, startTime, duration } = + entry as PerformanceNavigationTiming + + window.adobeDataLayer.push({ + event: "pageViewEnd", + pageInfo: pageObject, + userInfo: userData, + timing: { + duration, + loadEventEnd, + startTime, + }, + }) + } + }) + + perfObserver.observe({ + type: "navigation", + buffered: true, + }) + + setInitPerformanceTracking(true) + + // Cleanup function to disconnect the observer + return () => { + perfObserver.disconnect() + } + } + }, [pathName, pageData, userData, initPerformanceTracking]) + useEffect(() => { if (window.adobeDataLayer) { const trackingData = { ...pageData, pathName } const pageObject = createSDKPageObject(trackingData) - window.adobeDataLayer.push({ ...pageObject, userInfo: userData }) + + window.adobeDataLayer.push({ + event: "pageView", + pageInfo: pageObject, + userInfo: userData, + }) } }, [pathName, pageData, userData]) diff --git a/components/TrackingSDK/RouterTransition.tsx b/components/TrackingSDK/RouterTransition.tsx new file mode 100644 index 000000000..36525f9ad --- /dev/null +++ b/components/TrackingSDK/RouterTransition.tsx @@ -0,0 +1,33 @@ +"use client" + +import { useEffect, useOptimistic } from "react" + +import useRouterTransitionStore from "@/stores/router-transition" + +export default function RouterTransition() { + const [loading, setLoading] = useOptimistic(false) + const { isTransitioning, stopRouterTransition } = useRouterTransitionStore() + + useEffect(() => { + if (!isTransitioning) { + return + } + + if (isTransitioning) { + setLoading(true) + } + + if (!loading && isTransitioning) { + stopRouterTransition() + + // Send event to adobe that navigation transition is completed + if (window.adobeDataLayer) { + window.adobeDataLayer.push({ + event: "pageViewEnd", + }) + } + } + }, [isTransitioning, setLoading, loading, stopRouterTransition]) + + return null +} diff --git a/components/TrackingSDK/index.tsx b/components/TrackingSDK/index.tsx index 761169953..e725630e3 100644 --- a/components/TrackingSDK/index.tsx +++ b/components/TrackingSDK/index.tsx @@ -1,5 +1,7 @@ import { serverClient } from "@/lib/trpc/server" +import RouterTransition from "@/components/TrackingSDK/RouterTransition" + import TrackingSDKClient from "./Client" import { TrackingSDKPageData } from "@/types/components/tracking" @@ -15,5 +17,10 @@ export default async function TrackingSDK({ }) { const userTrackingData = await serverClient().user.tracking() - return + return ( + <> + + + + ) } diff --git a/stores/router-transition.ts b/stores/router-transition.ts new file mode 100644 index 000000000..7be183584 --- /dev/null +++ b/stores/router-transition.ts @@ -0,0 +1,21 @@ +"use client" + +import { createWithEqualityFn } from "zustand/traditional" + +interface RouterTransitionState { + isTransitioning: boolean + startRouterTransition: () => void + stopRouterTransition: () => void +} + +const useRouterTransitionStore = createWithEqualityFn( + (set) => ({ + isTransitioning: false, + startRouterTransition: () => + set((state) => ({ ...state, isTransitioning: true })), + stopRouterTransition: () => + set((state) => ({ ...state, isTransitioning: false })), + }) +) + +export default useRouterTransitionStore From 8e463ba552019c7e8e8ef4e0023fff93ecd29c9a Mon Sep 17 00:00:00 2001 From: Christel Westerberg Date: Wed, 21 Aug 2024 13:40:55 +0200 Subject: [PATCH 3/6] fix: move tracking out of navigation transition --- components/TempDesignSystem/Link/index.tsx | 2 +- components/TrackingSDK/RouterTransition.tsx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/components/TempDesignSystem/Link/index.tsx b/components/TempDesignSystem/Link/index.tsx index 8ef549d71..002fda960 100644 --- a/components/TempDesignSystem/Link/index.tsx +++ b/components/TempDesignSystem/Link/index.tsx @@ -70,8 +70,8 @@ export default function Link({ prefetch={prefetch} className={classNames} onClick={() => { + trackPageViewStart() startTransition(() => { - trackPageViewStart() startRouterTransition() router.push(href) }) diff --git a/components/TrackingSDK/RouterTransition.tsx b/components/TrackingSDK/RouterTransition.tsx index 36525f9ad..1b5de9346 100644 --- a/components/TrackingSDK/RouterTransition.tsx +++ b/components/TrackingSDK/RouterTransition.tsx @@ -1,6 +1,6 @@ "use client" -import { useEffect, useOptimistic } from "react" +import { startTransition, useEffect, useOptimistic } from "react" import useRouterTransitionStore from "@/stores/router-transition" @@ -14,7 +14,9 @@ export default function RouterTransition() { } if (isTransitioning) { - setLoading(true) + startTransition(() => { + setLoading(true) + }) } if (!loading && isTransitioning) { From b5d7931bc693191e56fab9d0a52c58c7ea881f14 Mon Sep 17 00:00:00 2001 From: Christel Westerberg Date: Fri, 23 Aug 2024 08:31:14 +0200 Subject: [PATCH 4/6] fix: faulty state --- components/TrackingSDK/Client.tsx | 4 ++-- stores/router-transition.ts | 18 ++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/components/TrackingSDK/Client.tsx b/components/TrackingSDK/Client.tsx index 850384f1a..5add36f8a 100644 --- a/components/TrackingSDK/Client.tsx +++ b/components/TrackingSDK/Client.tsx @@ -34,7 +34,7 @@ function createSDKPageObject(trackingData: TrackingSDKData) { export default function TrackingSDK({ pageData, userData }: TrackingSDKProps) { const pathName = usePathname() const isWebview = webviews.includes(pathName) - const [initPerformanceTracking, setInitPerformanceTracking] = useState(false) + const [initPerformanceTracking, setInitPerformanceTracking] = useState(true) const CookiebotCallbackOnAccept = useCallback(() => { const cookie = window._satellite.cookie.get("CookieConsent") @@ -90,7 +90,7 @@ export default function TrackingSDK({ pageData, userData }: TrackingSDKProps) { buffered: true, }) - setInitPerformanceTracking(true) + setInitPerformanceTracking(false) // Cleanup function to disconnect the observer return () => { diff --git a/stores/router-transition.ts b/stores/router-transition.ts index 7be183584..9fe9fd172 100644 --- a/stores/router-transition.ts +++ b/stores/router-transition.ts @@ -1,6 +1,6 @@ "use client" -import { createWithEqualityFn } from "zustand/traditional" +import { create } from "zustand" interface RouterTransitionState { isTransitioning: boolean @@ -8,14 +8,12 @@ interface RouterTransitionState { stopRouterTransition: () => void } -const useRouterTransitionStore = createWithEqualityFn( - (set) => ({ - isTransitioning: false, - startRouterTransition: () => - set((state) => ({ ...state, isTransitioning: true })), - stopRouterTransition: () => - set((state) => ({ ...state, isTransitioning: false })), - }) -) +const useRouterTransitionStore = create((set) => ({ + isTransitioning: false, + startRouterTransition: () => + set((state) => ({ ...state, isTransitioning: true })), + stopRouterTransition: () => + set((state) => ({ ...state, isTransitioning: false })), +})) export default useRouterTransitionStore From 12d2f82ba382c0a6a434d3381adc2ed1626c1b2e Mon Sep 17 00:00:00 2001 From: Christel Westerberg Date: Fri, 23 Aug 2024 08:50:34 +0200 Subject: [PATCH 5/6] fix: pass onclick prop to next link --- components/TempDesignSystem/Link/index.tsx | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/components/TempDesignSystem/Link/index.tsx b/components/TempDesignSystem/Link/index.tsx index 002fda960..8ef6452da 100644 --- a/components/TempDesignSystem/Link/index.tsx +++ b/components/TempDesignSystem/Link/index.tsx @@ -23,6 +23,7 @@ export default function Link({ prefetch, variant, trackingId, + onClick, ...props }: LinkProps) { const currentPageSlug = usePathname() @@ -53,26 +54,21 @@ export default function Link({ } }, [trackingId]) - useEffect(() => { - if (trackingId) { - const linkComponent = document.getElementById(trackingId) - - linkComponent?.addEventListener("click", trackClickById) - return () => { - linkComponent?.removeEventListener("click", trackClickById) - } - } - }, [trackClickById, trackingId]) - return ( { + onClick={(e) => { trackPageViewStart() startTransition(() => { startRouterTransition() + if (trackingId) { + trackClickById() + } + if (onClick) { + onClick(e) + } router.push(href) }) }} From 743e6873eff7e858302e6ffb9991838e293fccb7 Mon Sep 17 00:00:00 2001 From: Christel Westerberg Date: Fri, 23 Aug 2024 12:54:42 +0200 Subject: [PATCH 6/6] fix. refactor store --- stores/router-transition.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/stores/router-transition.ts b/stores/router-transition.ts index 9fe9fd172..0469868f3 100644 --- a/stores/router-transition.ts +++ b/stores/router-transition.ts @@ -10,10 +10,8 @@ interface RouterTransitionState { const useRouterTransitionStore = create((set) => ({ isTransitioning: false, - startRouterTransition: () => - set((state) => ({ ...state, isTransitioning: true })), - stopRouterTransition: () => - set((state) => ({ ...state, isTransitioning: false })), + startRouterTransition: () => set(() => ({ isTransitioning: true })), + stopRouterTransition: () => set(() => ({ isTransitioning: false })), })) export default useRouterTransitionStore