mirror of
https://github.com/Such-Software/such.software.git
synced 2026-10-17 05:32:05 +02:00
analytics: config-driven Umami tag + accurate privacy disclosure; fix @types/react v18/v19 dup that broke the build at HEAD
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
NEXT_PUBLIC_UMAMI_HOST=https://stats.suchshop.lol
|
||||||
|
NEXT_PUBLIC_UMAMI_WEBSITE_ID=62a3259a-8293-4e11-901c-d7fb86d30847
|
||||||
@@ -4,6 +4,7 @@ import "./globals.css";
|
|||||||
import { ThemeProvider } from "@/components/theme-provider";
|
import { ThemeProvider } from "@/components/theme-provider";
|
||||||
import { DynamicFavicon } from "@/components/dynamic-favicon";
|
import { DynamicFavicon } from "@/components/dynamic-favicon";
|
||||||
import { Footer } from "@/components/layout/footer";
|
import { Footer } from "@/components/layout/footer";
|
||||||
|
import { UmamiAnalytics } from "@/components/UmamiAnalytics";
|
||||||
|
|
||||||
const inter = Inter({ subsets: ["latin"] });
|
const inter = Inter({ subsets: ["latin"] });
|
||||||
|
|
||||||
@@ -119,6 +120,7 @@ export default function RootLayout({
|
|||||||
disableTransitionOnChange
|
disableTransitionOnChange
|
||||||
>
|
>
|
||||||
<DynamicFavicon />
|
<DynamicFavicon />
|
||||||
|
<UmamiAnalytics />
|
||||||
<div className="relative z-10 flex flex-col min-h-screen">
|
<div className="relative z-10 flex flex-col min-h-screen">
|
||||||
{children}
|
{children}
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export default function PrivacyPage() {
|
|||||||
<h1 className="text-4xl font-bold mb-8">Privacy Policy</h1>
|
<h1 className="text-4xl font-bold mb-8">Privacy Policy</h1>
|
||||||
|
|
||||||
<div className="prose dark:prose-invert max-w-none space-y-6">
|
<div className="prose dark:prose-invert max-w-none space-y-6">
|
||||||
<p className="text-muted-foreground">Last updated: April 9, 2026</p>
|
<p className="text-muted-foreground">Last updated: June 12, 2026</p>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h2 className="text-2xl font-semibold mt-8 mb-4">1. Who We Are</h2>
|
<h2 className="text-2xl font-semibold mt-8 mb-4">1. Who We Are</h2>
|
||||||
@@ -51,17 +51,25 @@ export default function PrivacyPage() {
|
|||||||
information with third parties.
|
information with third parties.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 className="text-xl font-medium mt-4 mb-2">Automatically Collected Information</h3>
|
<h3 className="text-xl font-medium mt-4 mb-2">Analytics</h3>
|
||||||
<p>
|
<p>
|
||||||
Our Site does not use analytics services, tracking pixels, or advertising cookies.
|
We use <strong>Umami</strong>, a privacy-respecting, self-hosted web analytics tool, to understand
|
||||||
We do not use Google Analytics, Facebook Pixel, or similar tracking tools on this website.
|
aggregate traffic to our Site (such as which pages are visited and where visitors arrive from).
|
||||||
|
Umami is <strong>cookieless</strong> and runs entirely on our own infrastructure — your data is
|
||||||
|
never sent to a third-party analytics provider or data broker. It does <strong>not</strong> store your
|
||||||
|
IP address, set tracking cookies, build cross-site profiles, or collect personally identifiable
|
||||||
|
information. We honor the <strong>Do Not Track</strong> and <strong>Global Privacy Control</strong>
|
||||||
|
browser signals: if either is enabled, no analytics are collected from your visit.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Our hosting infrastructure (Vercel) may collect standard server logs including IP addresses, browser type,
|
We do not use Google Analytics, Facebook Pixel, advertising cookies, or similar third-party tracking tools.
|
||||||
and pages visited. This data is used for security and performance purposes and is subject to{" "}
|
</p>
|
||||||
<a href="https://vercel.com/legal/privacy-policy" target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">
|
|
||||||
Vercel's Privacy Policy
|
<h3 className="text-xl font-medium mt-4 mb-2">Server Logs</h3>
|
||||||
</a>.
|
<p>
|
||||||
|
Our self-hosted infrastructure may record standard server logs (including IP addresses, browser type,
|
||||||
|
and pages visited) for security and performance purposes. These logs are not used to identify or
|
||||||
|
profile individual visitors and are retained only as long as needed for operational security.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 className="text-xl font-medium mt-4 mb-2">Cookies and Local Storage</h3>
|
<h3 className="text-xl font-medium mt-4 mb-2">Cookies and Local Storage</h3>
|
||||||
@@ -92,15 +100,15 @@ export default function PrivacyPage() {
|
|||||||
<h2 className="text-2xl font-semibold mt-8 mb-4">4. Third-Party Services</h2>
|
<h2 className="text-2xl font-semibold mt-8 mb-4">4. Third-Party Services</h2>
|
||||||
<p>The Site uses the following third-party services:</p>
|
<p>The Site uses the following third-party services:</p>
|
||||||
<ul className="list-disc pl-6 space-y-2">
|
<ul className="list-disc pl-6 space-y-2">
|
||||||
<li>
|
|
||||||
<strong>Vercel</strong> — hosting and deployment.{" "}
|
|
||||||
<a href="https://vercel.com/legal/privacy-policy" target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">Privacy Policy</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<strong>Cloudflare Turnstile</strong> — bot protection on the contact form.{" "}
|
<strong>Cloudflare Turnstile</strong> — bot protection on the contact form.{" "}
|
||||||
<a href="https://www.cloudflare.com/privacypolicy/" target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">Privacy Policy</a>
|
<a href="https://www.cloudflare.com/privacypolicy/" target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">Privacy Policy</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<p className="mt-4">
|
||||||
|
Our website analytics (Umami) and hosting are self-hosted on our own infrastructure and are therefore
|
||||||
|
not third-party services.
|
||||||
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
'use client';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
// Self-hosted, cookieless Umami — config via env so nothing is hardcoded.
|
||||||
|
// Honors Global Privacy Control + Do-Not-Track. No-op unless both env vars are set.
|
||||||
|
const HOST = process.env.NEXT_PUBLIC_UMAMI_HOST;
|
||||||
|
const WEBSITE_ID = process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID;
|
||||||
|
|
||||||
|
export function UmamiAnalytics() {
|
||||||
|
useEffect(() => {
|
||||||
|
if (!HOST || !WEBSITE_ID) return;
|
||||||
|
const nav = navigator as { globalPrivacyControl?: boolean };
|
||||||
|
if (nav.globalPrivacyControl) return;
|
||||||
|
if (document.querySelector(`script[data-website-id="${WEBSITE_ID}"]`)) return;
|
||||||
|
const s = document.createElement('script');
|
||||||
|
s.defer = true;
|
||||||
|
s.src = `${HOST}/script.js`;
|
||||||
|
s.setAttribute('data-website-id', WEBSITE_ID);
|
||||||
|
s.setAttribute('data-do-not-track', 'true');
|
||||||
|
document.head.appendChild(s);
|
||||||
|
}, []);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
+1
-1
@@ -20,7 +20,7 @@
|
|||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/react": "^18.0.0"
|
"@types/react": "^19.2.14"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"overrides": {
|
"overrides": {
|
||||||
|
|||||||
Reference in New Issue
Block a user