fix(web): remove Google Analytics from the site
The root layout loaded the gtag script for measurement ID G-7NBBNJNNQ7, and the privacy page described it. Remove both. The privacy page now says the site runs no analytics or tracking scripts, sets no cookies, and loads its header and footer logos from bongbetic.com. A jest test scans web/src, web/public and the next.config files for googletagmanager, google-analytics, gtag( and G- measurement IDs, so the tag cannot return unnoticed. Refs #16
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
// Ticket #16: the site loads no analytics. Everything the static export is
|
||||
// built from (web/src, web/public and the next.config files) is scanned byte
|
||||
// for byte, so a measurement tag cannot return through a component, an asset
|
||||
// or a config file. Binary assets are read as latin1 so every byte is covered.
|
||||
|
||||
const WEB_ROOT = process.cwd();
|
||||
const THIS_FILE = path.join(WEB_ROOT, 'src', 'app', '__tests__', 'no-analytics.test.ts');
|
||||
const TREE_ROOTS = [path.join(WEB_ROOT, 'src'), path.join(WEB_ROOT, 'public')];
|
||||
|
||||
const MARKERS: [string, RegExp][] = [
|
||||
['googletagmanager', /googletagmanager/],
|
||||
['google-analytics', /google-analytics/],
|
||||
['gtag(', /gtag\(/],
|
||||
['G- measurement ID', /G-[A-Z0-9]{8,}/],
|
||||
];
|
||||
|
||||
function scanTargets(): string[] {
|
||||
const targets: string[] = [];
|
||||
for (const root of TREE_ROOTS) {
|
||||
for (const rel of fs.readdirSync(root, { encoding: 'utf8', recursive: true })) {
|
||||
const full = path.join(root, rel);
|
||||
if (fs.statSync(full).isFile()) targets.push(full);
|
||||
}
|
||||
}
|
||||
for (const name of fs.readdirSync(WEB_ROOT)) {
|
||||
if (/^next\.config\./.test(name)) targets.push(path.join(WEB_ROOT, name));
|
||||
}
|
||||
return targets.filter((file) => file !== THIS_FILE);
|
||||
}
|
||||
|
||||
const sources = scanTargets().map((file) => ({
|
||||
file: path.relative(WEB_ROOT, file),
|
||||
text: fs.readFileSync(file, 'latin1'),
|
||||
}));
|
||||
|
||||
describe('no analytics on the site (ticket #16)', () => {
|
||||
it('scans the source, public assets and next.config files', () => {
|
||||
const names = sources.map((source) => source.file);
|
||||
expect(names).toEqual(
|
||||
expect.arrayContaining(['src/app/layout.tsx', 'next.config.js', 'public/_headers']),
|
||||
);
|
||||
});
|
||||
|
||||
it.each(MARKERS)('contains no %s marker', (_label, marker) => {
|
||||
const offenders = sources.filter((source) => marker.test(source.text)).map((source) => source.file);
|
||||
expect(offenders).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,6 @@
|
||||
import "@/styles/globals.css";
|
||||
import React from "react";
|
||||
import { type Metadata } from "next";
|
||||
import Script from "next/script";
|
||||
import {
|
||||
absoluteUrl,
|
||||
DEFAULT_OG_IMAGE_ALT,
|
||||
@@ -173,18 +172,6 @@ export default function RootLayout({
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<Script
|
||||
src="https://www.googletagmanager.com/gtag/js?id=G-7NBBNJNNQ7"
|
||||
strategy="lazyOnload"
|
||||
/>
|
||||
<Script id="google-analytics" strategy="lazyOnload">
|
||||
{`
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
gtag('config', 'G-7NBBNJNNQ7');
|
||||
`}
|
||||
</Script>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -24,7 +24,7 @@ export default function PrivacyPage() {
|
||||
headline: "Voculinux Privacy Policy",
|
||||
description:
|
||||
"How Voculinux handles voice data: local engines on your machine, optional Remote API to a server you configure.",
|
||||
dateModified: "2026-09-23",
|
||||
dateModified: "2026-11-06",
|
||||
author: {
|
||||
"@type": "Person",
|
||||
name: "Jatin K Malik",
|
||||
@@ -158,14 +158,13 @@ export default function PrivacyPage() {
|
||||
</h2>
|
||||
<div className="space-y-4 text-muted-foreground">
|
||||
<p>
|
||||
voculinux.com loads Google Analytics via the googletagmanager gtag
|
||||
script for measurement ID{" "}
|
||||
<code className="rounded bg-muted px-1.5 py-0.5">G-7NBBNJNNQ7</code>{" "}
|
||||
and runs gtag config with no IP anonymization and no cookie flags.
|
||||
That sends page views and a Google Analytics client identifier (a
|
||||
cookie) to Google. Google processes IP addresses and device and
|
||||
browser data. The installed Voculinux app does not send usage
|
||||
telemetry.
|
||||
voculinux.com has no analytics, measurement or tracking scripts,
|
||||
and its code sets no cookies.
|
||||
</p>
|
||||
<p>
|
||||
The Bongbetic logos in the header and footer are images served from
|
||||
bongbetic.com. Loading any page therefore makes a request to that
|
||||
host.
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
Reference in New Issue
Block a user