feat: add privacy-friendly Umami page-view analytics (#15)

Cookieless, env-gated page-view tracking via Umami. The <Analytics />
component injects the script only when NEXT_PUBLIC_UMAMI_SRC and
NEXT_PUBLIC_UMAMI_WEBSITE_ID are both set, so local dev and forks send
nothing to our instance. Adds .env.example docs (section 6) and a
homepage footer privacy disclosure. No Cookie consent banner needed.
This commit is contained in:
Zonghao Yuan
2026-06-03 01:14:55 +08:00
committed by GitHub
parent 639201cd38
commit 6ddbe7d377
4 changed files with 34 additions and 0 deletions
+12
View File
@@ -55,3 +55,15 @@ TTS_SPEECH_MODEL=mimo-v2.5-tts
# true → return a placeholder image instead of calling the image model.
# Text/story/voice still run normally. Great for iterating on TTS.
MOCK_IMAGE=false
# ---- 6. Analytics · Umami (optional — leave blank to disable) ------
# Privacy-friendly, cookieless page-view stats — no Cookie consent banner.
# Cloud: sign up at https://cloud.umami.is, add your site, copy its ID into
# NEXT_PUBLIC_UMAMI_WEBSITE_ID and use the cloud script URL:
# NEXT_PUBLIC_UMAMI_SRC=https://cloud.umami.is/script.js
# Self-host later: point SRC at your own instance — the integration is identical
# (no code change), e.g. NEXT_PUBLIC_UMAMI_SRC=https://stats.example.com/script.js
# Both blank → no script is injected (zero tracking). NEXT_PUBLIC_ vars are
# inlined at BUILD time, so set them in the build env (Vercel project settings).
NEXT_PUBLIC_UMAMI_SRC=
NEXT_PUBLIC_UMAMI_WEBSITE_ID=
+2
View File
@@ -1,5 +1,6 @@
import type { Metadata } from "next";
import { Cormorant_Garamond, Inter } from "next/font/google";
import { Analytics } from "@/components/Analytics";
import "./globals.css";
// Editorial fonts: drive tailwind `font-serif`/`font-sans` via
@@ -44,6 +45,7 @@ export default function RootLayout({
</head>
<body className="bg-cream-50 text-clay-900 font-sans antialiased min-h-screen overflow-x-hidden">
{children}
<Analytics />
</body>
</html>
);
+2
View File
@@ -744,6 +744,8 @@ export default function HomePage() {
<br />
AI
<br />
使 Umami 访使 Cookie
</p>
</section>
+18
View File
@@ -0,0 +1,18 @@
import Script from "next/script";
// Privacy-friendly, cookieless page-view analytics (Umami). Both env vars
// unset → render nothing, so local dev and forks never report to our instance.
export function Analytics() {
const src = process.env.NEXT_PUBLIC_UMAMI_SRC;
const websiteId = process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID;
if (!src || !websiteId) return null;
return (
<Script
src={src}
data-website-id={websiteId}
strategy="afterInteractive"
defer
/>
);
}