From d8f36271214e8b99db1199f4e13a4bd24016d75b Mon Sep 17 00:00:00 2001
From: Dawson Botsford <3408480+dawsbot@users.noreply.github.com>
Date: Mon, 6 Jul 2026 13:03:18 -0600
Subject: [PATCH] Replace dead react-ga with @vercel/analytics
react-ga v3 targets Google Universal Analytics, which was sunset in
July 2023, so the site has collected no analytics data since then.
- Remove react-ga, utils/analytics.js, and all initGA/logPageView/
logEvent wiring in components/layout.js and pages/index.js
- Add @vercel/analytics and render from a new
pages/_app.js per the Next.js pages-router docs (zero-config on
Vercel hosting)
Co-Authored-By: Claude Fable 5
---
components/layout.js | 12 -------
package-lock.json | 77 +++++++++++++++++++++++++++++++++-----------
package.json | 2 +-
pages/_app.js | 10 ++++++
pages/index.js | 4 ---
utils/analytics.js | 23 -------------
6 files changed, 69 insertions(+), 59 deletions(-)
create mode 100644 pages/_app.js
delete mode 100644 utils/analytics.js
diff --git a/components/layout.js b/components/layout.js
index 0755703..425c0c9 100644
--- a/components/layout.js
+++ b/components/layout.js
@@ -1,10 +1,7 @@
-import { useEffect } from "react";
import GHCorner from "react-github-corner";
import styled from "styled-components";
import { FaWrench } from "react-icons/fa";
-import { initGA, logPageView } from "../utils/analytics";
-
const Footer = styled.footer`
padding-top: 120px;
`;
@@ -25,15 +22,6 @@ const Wrench = styled(FaWrench)`
`;
export default ({ children }) => {
- useEffect(() => {
- /* eslint-disable */
- if (!window.GA_INITIALIZED) {
- initGA();
- window.GA_INITIALIZED = true;
- }
- /* eslint-enable */
- logPageView();
- }, []);
return (
= 13",
+ "nuxt": ">= 3",
+ "react": "^18 || ^19 || ^19.0.0-rc",
+ "svelte": ">= 4",
+ "vue": "^3",
+ "vue-router": "^4"
+ },
+ "peerDependenciesMeta": {
+ "@remix-run/react": {
+ "optional": true
+ },
+ "@sveltejs/kit": {
+ "optional": true
+ },
+ "next": {
+ "optional": true
+ },
+ "nuxt": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "svelte": {
+ "optional": true
+ },
+ "vue": {
+ "optional": true
+ },
+ "vue-router": {
+ "optional": true
+ }
+ }
+ },
"node_modules/acorn": {
"version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
@@ -3720,6 +3762,7 @@
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -4055,6 +4098,7 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dev": true,
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@@ -4064,7 +4108,8 @@
"node_modules/prop-types/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "dev": true
},
"node_modules/punycode": {
"version": "2.3.1",
@@ -4118,15 +4163,6 @@
"react": "^18.3.1"
}
},
- "node_modules/react-ga": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/react-ga/-/react-ga-3.3.1.tgz",
- "integrity": "sha512-4Vc0W5EvXAXUN/wWyxvsAKDLLgtJ3oLmhYYssx+YzphJpejtOst6cbIHCIyF50Fdxuf5DDKqRYny24yJ2y7GFQ==",
- "peerDependencies": {
- "prop-types": "^15.6.0",
- "react": "^15.6.2 || ^16.0 || ^17 || ^18"
- }
- },
"node_modules/react-github-corner": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/react-github-corner/-/react-github-corner-2.5.0.tgz",
@@ -5698,6 +5734,12 @@
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
"dev": true
},
+ "@vercel/analytics": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-2.0.1.tgz",
+ "integrity": "sha512-MTQG6V9qQrt1tsDeF+2Uoo5aPjqbVPys1xvnIftXSJYG2SrwXRHnqEvVoYID7BTruDz4lCd2Z7rM1BdkUehk2g==",
+ "requires": {}
+ },
"acorn": {
"version": "8.11.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
@@ -7781,7 +7823,8 @@
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
+ "dev": true
},
"object-inspect": {
"version": "1.13.1",
@@ -8000,6 +8043,7 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dev": true,
"requires": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@@ -8009,7 +8053,8 @@
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "dev": true
}
}
},
@@ -8042,12 +8087,6 @@
"scheduler": "^0.23.2"
}
},
- "react-ga": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/react-ga/-/react-ga-3.3.1.tgz",
- "integrity": "sha512-4Vc0W5EvXAXUN/wWyxvsAKDLLgtJ3oLmhYYssx+YzphJpejtOst6cbIHCIyF50Fdxuf5DDKqRYny24yJ2y7GFQ==",
- "requires": {}
- },
"react-github-corner": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/react-github-corner/-/react-github-corner-2.5.0.tgz",
diff --git a/package.json b/package.json
index 2af0d93..3d2360e 100644
--- a/package.json
+++ b/package.json
@@ -17,13 +17,13 @@
"prepare": "husky || true"
},
"dependencies": {
+ "@vercel/analytics": "^2.0.1",
"copy-to-clipboard": "^3.3.3",
"email-seems-valid": "^0.0.12",
"next": "^14.2.3",
"preact": "^10.22.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
- "react-ga": "^3.3.1",
"react-github-corner": "^2.5.0",
"react-icons": "^5.2.1",
"styled-components": "^6.1.11"
diff --git a/pages/_app.js b/pages/_app.js
new file mode 100644
index 0000000..36ac4a5
--- /dev/null
+++ b/pages/_app.js
@@ -0,0 +1,10 @@
+import { Analytics } from "@vercel/analytics/next";
+
+export default function MyApp({ Component, pageProps }) {
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/pages/index.js b/pages/index.js
index f456d72..2371e2f 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -9,7 +9,6 @@ import {
FaExternalLinkAlt,
} from "react-icons/fa";
import styled from "styled-components";
-import { logEvent } from "../utils/analytics";
import Layout from "../components/layout";
@@ -138,13 +137,11 @@ const MailTo = () => {
useFormState();
const handleResetState = () => {
- logEvent("reset", mailtoHref);
setCopied(false);
resetForm();
};
const handleCopy = () => {
- logEvent("copy-to-clipboard", mailtoHref);
copy(mailtoHref);
setCopied(true);
};
@@ -314,7 +311,6 @@ const MailTo = () => {
logEvent("open-mail-client", mailtoHref)}
target="_blank"
rel="noopener noreferrer"
aria-label="Open a test email in your default mail client"
diff --git a/utils/analytics.js b/utils/analytics.js
deleted file mode 100644
index f3eec7e..0000000
--- a/utils/analytics.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import ReactGA from "react-ga";
-export const initGA = () => {
- ReactGA.initialize(process.env.NEXT_PUBLIC_GA_TRACKING_ID);
-};
-export const logPageView = () => {
- // console.log('logging page view');
-
- ReactGA.set({ page: window.location.pathname });
- ReactGA.pageview(window.location.pathname);
-};
-export const logEvent = (action, mailtoHref) => {
- // console.log('logging event' + action + ' for href ' + mailtoHref);
- if (mailtoHref) {
- ReactGA.event({ category: "button-click", action, label: mailtoHref });
- return;
- }
- ReactGA.event({ category: "button-click", action });
-};
-export const logException = (description = "", fatal = false) => {
- if (description) {
- ReactGA.exception({ description, fatal });
- }
-};