wip: tinker with react-ga4
This commit is contained in:
Родитель
297939223e
Коммит
d7cfa68774
|
@ -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(
|
||||
|
|
|
@ -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",
|
||||
|
|
Загрузка…
Ссылка в новой задаче