From 37563741404e27bfc7e76e9b18056e271251155f Mon Sep 17 00:00:00 2001 From: rektdeckard Date: Sun, 5 Feb 2023 17:57:52 -0700 Subject: [PATCH] feat(analytics): migrate to GA4 --- package.json | 3 +- src/components/Banner/Banner.tsx | 2 +- src/components/IconGrid/DetailFooter.tsx | 6 +- src/components/IconGrid/DetailsPanel.tsx | 2 +- src/components/Links/Links.css | 1 + src/components/Links/Links.tsx | 53 +++++++--------- src/components/OutboundLink/OutboundLink.tsx | 64 ++++++++++++++++++++ src/components/OutboundLink/index.ts | 1 + src/components/SearchInput/SearchInput.tsx | 2 +- src/components/Tabs/Tabs.tsx | 1 + src/index.tsx | 6 +- 11 files changed, 99 insertions(+), 42 deletions(-) create mode 100644 src/components/OutboundLink/OutboundLink.tsx create mode 100644 src/components/OutboundLink/index.ts diff --git a/package.json b/package.json index 1fecf57..4c60ff0 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-dropdown-select": "^4.4.2", - "react-ga": "^3.1.2", + "react-ga4": "^2.0.0", "react-hotkeys-hook": "^3.2.1", "react-use": "^17.4.0", "recoil": "^0.7.6", @@ -49,7 +49,6 @@ "@types/node": "^18.11.18", "@types/react": "^18.0.27", "@types/react-dom": "^18.0.10", - "@types/react-virtualized": "^9.21.10", "@types/tinycolor2": "^1.4.3", "@vitejs/plugin-react": "^3.1.0", "typescript": "^4.9.5", diff --git a/src/components/Banner/Banner.tsx b/src/components/Banner/Banner.tsx index 66e2628..8d5c6eb 100644 --- a/src/components/Banner/Banner.tsx +++ b/src/components/Banner/Banner.tsx @@ -1,5 +1,5 @@ import { Medal } from "phosphor-react"; -import ReactGA from "react-ga"; +import ReactGA from "react-ga4"; import "./Banner.css"; diff --git a/src/components/IconGrid/DetailFooter.tsx b/src/components/IconGrid/DetailFooter.tsx index 06c4334..33b2fc7 100644 --- a/src/components/IconGrid/DetailFooter.tsx +++ b/src/components/IconGrid/DetailFooter.tsx @@ -4,8 +4,8 @@ import { useHotkeys } from "react-hotkeys-hook"; import { motion, AnimatePresence, Variants } from "framer-motion"; import { Svg2Png } from "svg2png-converter"; import { saveAs } from "file-saver"; -import { Copy, X, CheckCircle, Download } from "phosphor-react"; -import ReactGA from "react-ga"; +import { Copy, CheckCircle, Download } from "phosphor-react"; +import ReactGA from "react-ga4"; import { iconWeightAtom, @@ -16,7 +16,7 @@ import { import { isDarkThemeSelector } from "@/state/selectors"; import Tabs, { Tab } from "@/components/Tabs"; import useTransientState from "@/hooks/useTransientState"; -import { IconEntry, SnippetType } from "@/lib"; +import { SnippetType } from "@/lib"; import { getCodeSnippets, supportsWeight } from "@/utils"; import TagCloud from "./TagCloud"; diff --git a/src/components/IconGrid/DetailsPanel.tsx b/src/components/IconGrid/DetailsPanel.tsx index 1be8e03..f02a056 100644 --- a/src/components/IconGrid/DetailsPanel.tsx +++ b/src/components/IconGrid/DetailsPanel.tsx @@ -5,7 +5,7 @@ import { motion } from "framer-motion"; import { Svg2Png } from "svg2png-converter"; import { saveAs } from "file-saver"; import { Copy, X, CheckCircle, Download } from "phosphor-react"; -import ReactGA from "react-ga"; +import ReactGA from "react-ga4"; import { iconWeightAtom, diff --git a/src/components/Links/Links.css b/src/components/Links/Links.css index fd241ef..710549d 100644 --- a/src/components/Links/Links.css +++ b/src/components/Links/Links.css @@ -23,6 +23,7 @@ a.nav-link { text-decoration: none; position: relative; + cursor: pointer; color: black; } diff --git a/src/components/Links/Links.tsx b/src/components/Links/Links.tsx index c4d458b..d43e2bc 100644 --- a/src/components/Links/Links.tsx +++ b/src/components/Links/Links.tsx @@ -1,7 +1,7 @@ -import { OutboundLink } from "react-ga"; import { ArrowElbowDownRight } from "phosphor-react"; import { iconCount } from "@/lib/icons"; +import OutboundLink from "@/components/OutboundLink"; import "./Links.css"; @@ -14,7 +14,7 @@ const Links = (_: LinksProps) => { { Download all ({iconCount}) +
Figma library {" / "} plugin
+
{ Sketch plugin
+
- + Donate on PayPal - + {" / "} - + Patreon - +
- {/*
- - - Donate on PayPal - -
+
- - Support us on Patreon - -
- */} -
- - GitHub - +
- Request an icon - +
); diff --git a/src/components/OutboundLink/OutboundLink.tsx b/src/components/OutboundLink/OutboundLink.tsx new file mode 100644 index 0000000..4234e67 --- /dev/null +++ b/src/components/OutboundLink/OutboundLink.tsx @@ -0,0 +1,64 @@ +import { + DetailedHTMLProps, + AnchorHTMLAttributes, + useCallback, + MouseEventHandler, +} from "react"; +import ReactGA from "react-ga4"; +import { UaEventOptions } from "react-ga4/types/ga4"; + +interface OutboundLinkProps + extends DetailedHTMLProps< + AnchorHTMLAttributes, + HTMLAnchorElement + > { + eventLabel: string; +} + +const NEWTAB = "_blank"; +const MIDDLECLICK = 1; +const DEFAULT_META: UaEventOptions = { + category: "Outbound", + action: "Click", +}; + +const OutboundLink = ({ + eventLabel, + target, + href, + ...props +}: OutboundLinkProps) => { + const handleClick: MouseEventHandler = useCallback( + (event) => { + const eventMeta = { ...DEFAULT_META, label: eventLabel }; + const sameTarget = target !== NEWTAB; + const normalClick = !( + event.ctrlKey || + event.shiftKey || + event.metaKey || + event.button === MIDDLECLICK + ); + + if (!!href && sameTarget && normalClick) { + event.preventDefault(); + ReactGA.event(eventMeta); + window.location.href = href; + } else { + ReactGA.event(eventMeta); + } + }, + [href, eventLabel] + ); + + return ( + + ); +}; + +export default OutboundLink; diff --git a/src/components/OutboundLink/index.ts b/src/components/OutboundLink/index.ts new file mode 100644 index 0000000..b54bc9a --- /dev/null +++ b/src/components/OutboundLink/index.ts @@ -0,0 +1 @@ +export { default } from "./OutboundLink"; diff --git a/src/components/SearchInput/SearchInput.tsx b/src/components/SearchInput/SearchInput.tsx index e886447..688f6e3 100644 --- a/src/components/SearchInput/SearchInput.tsx +++ b/src/components/SearchInput/SearchInput.tsx @@ -9,7 +9,7 @@ import { useRecoilState } from "recoil"; import { useDebounce } from "react-use"; import { useHotkeys } from "react-hotkeys-hook"; import { Command, MagnifyingGlass, X, HourglassHigh } from "phosphor-react"; -import ReactGA from "react-ga"; +import ReactGA from "react-ga4"; import { searchQueryAtom } from "@/state/atoms"; import "./SearchInput.css"; diff --git a/src/components/Tabs/Tabs.tsx b/src/components/Tabs/Tabs.tsx index 06d1ecd..5de51a2 100644 --- a/src/components/Tabs/Tabs.tsx +++ b/src/components/Tabs/Tabs.tsx @@ -19,6 +19,7 @@ const Tabs = ({ tabs }: TabsProps) => {
{tabs.map((tab, i) => (