diff --git a/pages/_app.tsx b/pages/_app.tsx
index 2bf0bbb491..9c43d15419 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -1,11 +1,11 @@
-import { useEffect } from "react";
+import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import Script from "next/script";
import type { AppProps } from "next/app";
import { DocsContextProvider } from "layouts/DocsPage/context";
-import { posthog, sendPageview } from "utils/posthog";
+import { posthog, sendEngagedView, sendPageview } from "utils/posthog";
import { TabContextProvider } from "components/Tabs";
-
+import { TrackingEvent } from "utils/tracking";
// https://larsmagnus.co/blog/how-to-optimize-custom-fonts-with-next-font
// Next Font to enable zero layout shift which is hurting SEO.
import localUbuntu from "next/font/local";
@@ -68,7 +68,32 @@ interface dataLayerItem {
declare global {
var dataLayer: dataLayerItem[]; // eslint-disable-line no-var
}
+const useIsEngaged = () => {
+ const router = useRouter();
+ const [timerReached, setTimerReached] = useState(false);
+ const [secondPageReached, setSecondPageReached] = useState(false);
+ const [isEngaged, setIsEngaged] = useState(false);
+
+ useEffect(() => {
+ setTimeout(() => {
+ setTimerReached(true);
+ }, 30000);
+ const routeChanged = () => {
+ setSecondPageReached(true);
+ };
+
+ router.events.on("routeChangeComplete", routeChanged);
+ return () => {
+ router.events.off("routeChangeComplete", routeChanged);
+ };
+ }, [router.events]);
+
+ useEffect(() => {
+ setIsEngaged(secondPageReached && timerReached);
+ }, [secondPageReached, timerReached]);
+ return isEngaged;
+};
const Analytics = () => {
return (
<>
@@ -163,6 +188,45 @@ const Analytics = () => {
{/* End Google Tag Manager (noscript) */}
>
)}
+ {/* LinkedIn Tracking script */}
+
+
+
+ {/* Quailified Script */}
+
+
{NEXT_PUBLIC_REDDIT_ID && (
<>
@@ -180,14 +244,32 @@ const Analytics = () => {
const MyApp = ({ Component, pageProps }: AppProps) => {
const router = useRouter();
+ const isEngaged = useIsEngaged();
useEffect(() => {
- posthog(); // init posthog
-
- router.events.on("routeChangeComplete", sendPageview);
+ if (!isEngaged) return;
+ // Trigger engagement view events here
+ // Linked in engagement view
+ window["lintrk"]("track", { conversion_id: 14913124 });
+ sendEngagedView();
+ }, [isEngaged]);
+ const Pageviews = () => {
+ // Trigger page views here
+ // Linked In Docs Page Visit
+ window["lintrk"]("track", { conversion_id: 14913132 });
+ // Qualified page view
+ if (!!window["qualified"]) window["qualified"]("page");
+ // Posthog page view
+ sendPageview();
+ };
+ useEffect(() => {
+ posthog(); // init posthog
+ // Trigger initial load page views
+ Pageviews();
+ router.events.on("routeChangeComplete", Pageviews);
return () => {
- router.events.off("routeChangeComplete", sendPageview);
+ router.events.off("routeChangeComplete", Pageviews);
};
}, [router.events]);
diff --git a/utils/posthog.ts b/utils/posthog.ts
index f1108289d2..8d6cb7c85e 100644
--- a/utils/posthog.ts
+++ b/utils/posthog.ts
@@ -49,3 +49,11 @@ export const sendDocsFeedback = async (rating: string, comment: string) => {
"web.docs.comment": comment,
});
};
+
+export const sendEngagedView = async () => {
+ const ph = await posthog();
+ ph?.capture("web.engagement.timer", {
+ "web.engagement.sessionTimerThreshold": 30,
+ "web.engagement.sessionPageThreshold": 2,
+ });
+};
diff --git a/utils/tracking.ts b/utils/tracking.ts
new file mode 100644
index 0000000000..b9e00e5a46
--- /dev/null
+++ b/utils/tracking.ts
@@ -0,0 +1,34 @@
+const isDatalayerEnabled = () => {
+ typeof window !== "undefined" && !!window.dataLayer;
+};
+
+// Wrapper around datalayer calls to prevent errors
+
+export const TrackingEvent = (
+ event: string,
+ payload: Record = {}
+): Promise => {
+ return new Promise((resolve) => {
+ if (isDatalayerEnabled) {
+ window.dataLayer.push({
+ event,
+ ...payload,
+ /* eventCallback and eventTimeout are not found in GTM official docs!
+ eventCallback is a function which will execute when all tags which fire on
+ the event have executed; it is scoped to this promise. Always add eventTimeout
+ when you use eventCallback.
+ */
+ eventCallback: () => resolve(),
+
+ /*eventTimeout takes a number in milliseconds as a value after which it calls eventCallback, so
+ even if the tags don't fire or signal completion, eventCallback will be invoked (and
+ this promise resolved)
+ */
+ eventTimeout: 1000,
+ });
+ } else {
+ console.log("Datalayer Tracking Event", payload);
+ resolve();
+ }
+ });
+};