Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,11 @@ GA4_MEASUREMENT_ID=
# Protocol API secrets. Leaking it lets anyone forge events into your GA4
# property. Required only if GA4_MEASUREMENT_ID is set.
GA4_API_SECRET=

# [PUBLIC] [optional] GA4 Measurement ID for client-side gtag.js page-view
# tracking. Format: "G-XXXXXXXXXX". Inlined into the bundle at build time
# via the NEXT_PUBLIC_ prefix — served to every visitor in the gtag.js
# script src, so not sensitive. When unset, app/layout.tsx skips rendering
# the GA4 <Script> tags entirely. Typically the same value as
# GA4_MEASUREMENT_ID (same GA4 property) — keep them in sync.
NEXT_PUBLIC_GA4_MEASUREMENT_ID=
20 changes: 20 additions & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import Script from "next/script";
import { Header } from "@/components/header";
import { Footer } from "@/components/ui/footer";
import "./globals.css";
Expand All @@ -26,6 +27,8 @@ export default function RootLayout({
}: {
children: React.ReactNode;
}) {
const gaId = process.env.NEXT_PUBLIC_GA4_MEASUREMENT_ID;

return (
<html lang="en">
<body className={`${inter.className}`}>
Expand All @@ -36,6 +39,23 @@ export default function RootLayout({
</section>

<Footer />

{gaId && (
<>
<Script
src={`https://www.googletagmanager.com/gtag/js?id=${gaId}`}
strategy="afterInteractive"
/>
<Script id="ga4-init" strategy="afterInteractive">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${gaId}');
`}
</Script>
</>
)}
</body>
</html>
);
Expand Down
8 changes: 8 additions & 0 deletions types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ declare namespace NodeJS {
GA4_MEASUREMENT_ID: string;
GA4_API_SECRET: string;

/**
* Client-side analytics (gtag.js). Optional — the GA4 <Script>
* tags in app/layout.tsx render only when this is set. Public by
* design (served to every visitor in the script src), so safe to
* expose with the NEXT_PUBLIC_ prefix.
*/
NEXT_PUBLIC_GA4_MEASUREMENT_ID: string;

/**
* Auth related variables
*/
Expand Down
Loading