Skip to content

Commit c0e5d46

Browse files
committed
feat: Add layout tag manager
1 parent 7d44454 commit c0e5d46

File tree

4 files changed

+70
-2
lines changed

4 files changed

+70
-2
lines changed

apps/web/app/Layout/GTag.tsx

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"use client";
2+
3+
import { buildEnv } from "@cap/env";
4+
import Script from "next/script";
5+
import { useId, useRef } from "react";
6+
7+
declare global {
8+
interface Window {
9+
gtag: (command: string, ...args: unknown[]) => void;
10+
dataLayer: unknown[];
11+
}
12+
}
13+
14+
export function GTag() {
15+
const gtagInitialized = useRef(false);
16+
const awId = buildEnv.NEXT_PUBLIC_GOOGLE_AW_ID;
17+
const scriptId = useId();
18+
19+
if (!awId) {
20+
return null;
21+
}
22+
23+
if (typeof window !== "undefined" && !window.dataLayer) {
24+
window.dataLayer = window.dataLayer || [];
25+
window.gtag = function gtag() {
26+
window.dataLayer.push(arguments);
27+
};
28+
}
29+
30+
return (
31+
<>
32+
<Script
33+
id={scriptId}
34+
strategy="afterInteractive"
35+
src={`https://www.googletagmanager.com/gtag/js?id=${awId}`}
36+
onLoad={() => {
37+
if (
38+
!gtagInitialized.current &&
39+
typeof window !== "undefined" &&
40+
window.gtag &&
41+
awId
42+
) {
43+
window.gtag("js", new Date());
44+
window.gtag("config", awId);
45+
gtagInitialized.current = true;
46+
}
47+
}}
48+
/>
49+
</>
50+
);
51+
}
52+
53+
export function trackGoogleEvent(
54+
action: string,
55+
parameters?: Record<string, unknown>,
56+
) {
57+
if (typeof window !== "undefined" && window.gtag) {
58+
try {
59+
window.gtag("event", action, parameters);
60+
} catch (error) {
61+
console.error(`Error tracking Google event ${action}:`, error);
62+
}
63+
}
64+
}

apps/web/app/layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { SonnerToaster } from "@/components/SonnerToastProvider";
1111
import { getBootstrapData } from "@/utils/getBootstrapData";
1212
import { PublicEnvContext } from "@/utils/public-env";
1313
import { AuthContextProvider } from "./Layout/AuthContext";
14+
import { GTag } from "./Layout/GTag";
1415
import { MetaPixel } from "./Layout/MetaPixel";
1516
import { PosthogIdentify } from "./Layout/PosthogIdentify";
1617
import { PurchaseTracker } from "./Layout/PurchaseTracker";
@@ -123,6 +124,7 @@ export default async function RootLayout({ children }: PropsWithChildren) {
123124
<main className="w-full">{children}</main>
124125
<PosthogIdentify />
125126
<MetaPixel />
127+
<GTag />
126128
<PurchaseTracker />
127129
</ReactQueryProvider>
128130
</PublicEnvContext>

apps/web/components/pages/_components/ComparePlans.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import { toast } from "sonner";
1010
import { useAuthContext } from "@/app/Layout/AuthContext";
1111
import {
1212
CommercialArt,
13-
CommercialArtRef,
13+
type CommercialArtRef,
1414
} from "../HomePage/Pricing/CommercialArt";
15-
import { ProArt, ProArtRef } from "../HomePage/Pricing/ProArt";
15+
import { ProArt, type ProArtRef } from "../HomePage/Pricing/ProArt";
1616

1717
const COLUMN_WIDTH = "min-w-[200px]";
1818

packages/env/build.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const buildEnv = createEnv({
1111
NEXT_PUBLIC_POSTHOG_KEY: z.string().optional(),
1212
NEXT_PUBLIC_POSTHOG_HOST: z.string().optional(),
1313
NEXT_PUBLIC_META_PIXEL_ID: z.string().optional(),
14+
NEXT_PUBLIC_GOOGLE_AW_ID: z.string().optional(),
1415
NEXT_PUBLIC_WEB_URL: z.string(),
1516
NEXT_PUBLIC_CAP_AWS_BUCKET: z.string(),
1617
NEXT_PUBLIC_CAP_AWS_REGION: z.string(),
@@ -23,6 +24,7 @@ export const buildEnv = createEnv({
2324
NEXT_PUBLIC_POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY,
2425
NEXT_PUBLIC_POSTHOG_HOST: process.env.NEXT_PUBLIC_POSTHOG_HOST,
2526
NEXT_PUBLIC_META_PIXEL_ID: process.env.NEXT_PUBLIC_META_PIXEL_ID,
27+
NEXT_PUBLIC_GOOGLE_AW_ID: process.env.NEXT_PUBLIC_GOOGLE_AW_ID,
2628
NEXT_PUBLIC_WEB_URL: process.env.WEB_URL ?? process.env.NEXT_PUBLIC_WEB_URL,
2729
NEXT_PUBLIC_CAP_AWS_BUCKET:
2830
process.env.CAP_AWS_BUCKET ?? process.env.NEXT_PUBLIC_CAP_AWS_BUCKET,

0 commit comments

Comments
 (0)