This commit is contained in:
groovecoder 2024-06-12 16:36:05 -05:00
Родитель 297939223e
Коммит d7cfa68774
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4825AB58E974B712
7 изменённых файлов: 111 добавлений и 14 удалений

Просмотреть файл

@ -55,5 +55,11 @@ module.exports = {
files: ["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[jt]s?(x)"],
extends: ["plugin:testing-library/react"],
},
{
files: ["src/hooks/gaEvent.ts"],
rules: {
"@typescript-eslint/no-explicit-any": "warn",
},
},
],
};

Просмотреть файл

@ -30,6 +30,7 @@
"react-confetti": "^6.1.0",
"react-dom": "18.3.1",
"react-ga": "^3.3.1",
"react-ga4": "^2.1.0",
"react-intersection-observer": "^9.10.3",
"react-singleton-hook": "^4.0.1",
"react-stately": "^3.31.1",

Просмотреть файл

@ -0,0 +1,69 @@
import React from "react";
import ReactGA from "react-ga4";
export type TrackerNames = string[];
export interface OutboundLinkProps {
eventLabel?: string;
to?: string;
target?: string;
onClick?: () => void;
trackerNames?: TrackerNames;
}
const NEWTAB = "_blank";
const MIDDLECLICK = 1;
export default class OutboundLink extends React.Component {
props: OutboundLinkProps & React.HTMLProps<HTMLAnchorElement> = {};
static trackLink = (eventMeta, hitCallback, _trackerNames) => {
ReactGA.outboundLink(eventMeta, hitCallback);
};
handleClick = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
const { target, eventLabel, to, onClick, trackerNames } = this.props;
const eventMeta = { label: eventLabel };
const sameTarget = target !== NEWTAB;
const normalClick = !(
event.ctrlKey ||
event.shiftKey ||
event.metaKey ||
event.button === MIDDLECLICK
);
if (sameTarget && normalClick) {
event.preventDefault();
OutboundLink.trackLink(
eventMeta,
() => {
window.location.href = to;
},
trackerNames,
);
} else {
OutboundLink.trackLink(eventMeta, () => {}, trackerNames);
}
if (onClick) {
onClick(event);
}
};
render() {
const { to: href, target, ...oldProps } = this.props;
const props = {
...oldProps,
target,
href,
onClick: this.handleClick,
};
if (target === NEWTAB) {
props.rel = `${props.rel ? props.rel : ""} noopener noreferrer`.trim();
}
delete props.eventLabel;
delete props.trackerNames;
return React.createElement("a", props);
}
}

Просмотреть файл

@ -1,14 +1,14 @@
import { event, EventArgs } from "react-ga";
import ReactGA from "react-ga4";
import { UaEventOptions } from "react-ga4/types/ga4";
import { useGoogleAnalytics } from "./googleAnalytics";
export type { EventArgs };
function dropGaEvent(_args: EventArgs) {}
function dropGaEvent(_optionsOrName: UaEventOptions | string, _params?: any) {}
/**
* Returns a function that sends a ping if there is no user or the user has enabled metrics.
*/
export function useGaEvent() {
const googleAnalytics = useGoogleAnalytics();
return googleAnalytics ? event : dropGaEvent;
return googleAnalytics ? ReactGA.event : dropGaEvent;
}

Просмотреть файл

@ -1,4 +1,4 @@
import ReactGa from "react-ga";
import ReactGA from "react-ga4";
import { useState } from "react";
import { singletonHook } from "react-singleton-hook";
import { getRuntimeConfig } from "../config";
@ -13,11 +13,20 @@ export const useGoogleAnalytics = singletonHook(gaIsInitialized, () => {
});
export function initGoogleAnalytics() {
ReactGa.initialize(getRuntimeConfig().googleAnalyticsId, {
titleCase: false,
debug: process.env.NEXT_PUBLIC_DEBUG === "true",
});
ReactGa.set({
ReactGA.initialize([
{
trackingId: getRuntimeConfig().googleAnalyticsId,
gaOptions: {
title_case: false,
debug_mode: process.env.NEXT_PUBLIC_DEBUG === "true",
},
gtagOptions: {
title_case: false,
debug_mode: process.env.NEXT_PUBLIC_DEBUG === "true",
},
},
]);
ReactGA.set({
anonymizeIp: true,
transport: "beacon",
});
@ -28,7 +37,7 @@ export function initGoogleAnalytics() {
gaEventCookies.forEach((item) => {
const serverEventLabel = item.split("=")[1];
if (serverEventLabel) {
ReactGa.event({
ReactGA.event({
category: "server event",
action: "fired",
label: serverEventLabel,

Просмотреть файл

@ -4,7 +4,7 @@ import type { AppProps } from "next/app";
import { useRouter } from "next/router";
import { LocalizationProvider, ReactLocalization } from "@fluent/react";
import { OverlayProvider } from "@react-aria/overlays";
import ReactGa from "react-ga";
import ReactGA from "react-ga4";
import { getL10n } from "../functions/getL10n";
import { AddonDataContext, useAddonElementWatcher } from "../hooks/addon";
import { ReactAriaI18nProvider } from "../components/ReactAriaI18nProvider";
@ -48,7 +48,7 @@ function MyApp({ Component, pageProps }: AppProps) {
useEffect(() => {
if (!googleAnalytics) return;
ReactGa.pageview(router.asPath);
ReactGA.send({ hitType: "pageview", page: router.asPath });
}, [router.asPath, googleAnalytics]);
const [waitingForMsw, setIsWaitingForMsw] = useState(

12
package-lock.json сгенерированный
Просмотреть файл

@ -34,6 +34,7 @@
"react-confetti": "^6.1.0",
"react-dom": "18.3.1",
"react-ga": "^3.3.1",
"react-ga4": "^2.1.0",
"react-intersection-observer": "^9.10.3",
"react-singleton-hook": "^4.0.1",
"react-stately": "^3.31.1",
@ -12651,6 +12652,11 @@
"react": "^15.6.2 || ^16.0 || ^17 || ^18"
}
},
"node_modules/react-ga4": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/react-ga4/-/react-ga4-2.1.0.tgz",
"integrity": "sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ=="
},
"node_modules/react-intersection-observer": {
"version": "9.10.3",
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.10.3.tgz",
@ -20337,6 +20343,7 @@
"react-confetti": "^6.1.0",
"react-dom": "18.3.1",
"react-ga": "^3.3.1",
"react-ga4": "^2.1.0",
"react-intersection-observer": "^9.10.3",
"react-singleton-hook": "^4.0.1",
"react-stately": "^3.31.1",
@ -23782,6 +23789,11 @@
"version": "3.3.1",
"requires": {}
},
"react-ga4": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/react-ga4/-/react-ga4-2.1.0.tgz",
"integrity": "sha512-ZKS7PGNFqqMd3PJ6+C2Jtz/o1iU9ggiy8Y8nUeksgVuvNISbmrQtJiZNvC/TjDsqD0QlU5Wkgs7i+w9+OjHhhQ=="
},
"react-intersection-observer": {
"version": "9.10.3",
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-9.10.3.tgz",