From b48be218402f8a7e73091340f12708add0aaff17 Mon Sep 17 00:00:00 2001 From: An-Ting Hsu <12019694+andyhsu10@users.noreply.github.com> Date: Wed, 10 Jun 2026 17:13:25 +0800 Subject: [PATCH] feat: optional Google Analytics 4 via @next/third-parties GA loads only when NEXT_PUBLIC_GA_ID is set, so local dev and PR previews stay untracked. Production reads it from a GitHub Actions repo variable. Co-Authored-By: Claude Opus 4.8 (1M context) --- .env.example | 4 ++++ .github/workflows/deploy.yml | 2 ++ app/layout.tsx | 6 ++++++ package.json | 1 + pnpm-lock.yaml | 20 ++++++++++++++++++++ 5 files changed, 33 insertions(+) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..2ed03cc --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +# Google Analytics 4 Measurement ID. Leave empty to disable GA. +# Local dev: copy this file to `.env.local` and fill in your ID. +# Production: set as a GitHub Actions repository variable named NEXT_PUBLIC_GA_ID. +NEXT_PUBLIC_GA_ID= diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 7d20438..1c2a076 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,6 +41,8 @@ jobs: cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm build + env: + NEXT_PUBLIC_GA_ID: ${{ vars.NEXT_PUBLIC_GA_ID }} - uses: actions/upload-pages-artifact@v3 with: path: out diff --git a/app/layout.tsx b/app/layout.tsx index a68bd4a..7845e70 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,7 +1,12 @@ import type { Metadata } from "next"; import { Inter, JetBrains_Mono } from "next/font/google"; +import { GoogleAnalytics } from "@next/third-parties/google"; import "./globals.css"; +// Set NEXT_PUBLIC_GA_ID (e.g. "G-XXXXXXXXXX") to enable Google Analytics. +// When unset (local dev, PR previews), GA is not loaded. +const gaId = process.env.NEXT_PUBLIC_GA_ID; + const inter = Inter({ subsets: ["latin"], variable: "--font-inter" }); const jetbrains = JetBrains_Mono({ subsets: ["latin"], variable: "--font-jetbrains" }); @@ -28,6 +33,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })