feat: add react-ga events

This commit is contained in:
AykutSarac 2023-07-20 20:14:33 +03:00
parent 5bcc9b0c7c
commit d2b7d94183
No known key found for this signature in database
12 changed files with 74 additions and 6 deletions

View File

@ -40,6 +40,7 @@
"react": "^18.2.0",
"react-color": "^2.19.3",
"react-dom": "^18.2.0",
"react-ga": "^3.3.1",
"react-hot-toast": "^2.4.1",
"react-icons": "^4.10.1",
"react-linkify-it": "^1.0.7",

View File

@ -1,9 +1,12 @@
import React from "react";
import Script from "next/script";
import ReactGA from "react-ga";
const isDevelopment = process.env.NODE_ENV === "development";
const GA_TRACKING_ID = process.env.NEXT_PUBLIC_GA_ID;
ReactGA.initialize(GA_TRACKING_ID, { testMode: isDevelopment });
const GoogleAnalytics: React.FC = () => {
if (isDevelopment) return null;

View File

@ -149,7 +149,13 @@ export const Graph = ({ isWidget = false }: GraphProps) => {
return (
<>
<Loading message="Painting graph..." loading={loading} />
<StyledEditorWrapper onContextMenu={e => e.preventDefault()} widget={isWidget}>
<StyledEditorWrapper
onClick={() => {
if ("activeElement" in document) (document.activeElement as HTMLElement)?.blur();
}}
onContextMenu={e => e.preventDefault()}
widget={isWidget}
>
<TransformWrapper
maxScale={2}
minScale={0.05}

View File

@ -1,6 +1,7 @@
import React from "react";
import { Flex, Input, Text } from "@mantine/core";
import { getHotkeyHandler } from "@mantine/hooks";
import { event } from "react-ga";
import { AiOutlineSearch } from "react-icons/ai";
import { useFocusNode } from "src/hooks/useFocusNode";
@ -14,6 +15,7 @@ export const SearchInput: React.FC = () => {
id="search-node"
value={searchValue}
onChange={e => setValue(e.currentTarget.value)}
onFocus={() => event({ action: "focus_node_search", category: "User" })}
placeholder="Search Node"
onKeyDown={getHotkeyHandler([["Enter", skip]])}
icon={<AiOutlineSearch />}

View File

@ -2,6 +2,7 @@ import React from "react";
import styled from "styled-components";
import { Flex, Group, MediaQuery, Menu, Select, Text } from "@mantine/core";
import { useHotkeys } from "@mantine/hooks";
import { event } from "react-ga";
import toast from "react-hot-toast";
import { AiOutlineFullscreen, AiOutlineMinus, AiOutlinePlus } from "react-icons/ai";
import { CgArrowsMergeAltH, CgArrowsShrinkH, CgChevronDown } from "react-icons/cg";
@ -207,7 +208,10 @@ export const Tools: React.FC<{ isWidget?: boolean }> = ({ isWidget = false }) =>
<Menu.Dropdown>
<Menu.Item
fz={12}
onClick={toggleEditor}
onClick={() => {
toggleEditor();
event({ action: "toggle_hide_editor", category: "User", label: "Tools" });
}}
icon={fullscreen ? <VscLayoutSidebarLeft /> : <VscLayoutSidebarLeftOff />}
rightSection={
<Text ml="md" fz={10} color="dimmed">
@ -219,7 +223,10 @@ export const Tools: React.FC<{ isWidget?: boolean }> = ({ isWidget = false }) =>
</Menu.Item>
<Menu.Item
fz={12}
onClick={toggleDirection}
onClick={() => {
toggleDirection();
event({ action: "toggle_layout_direction", category: "User", label: "Tools" });
}}
icon={<StyledFlowIcon rotate={rotateLayout(direction)} />}
rightSection={
<Text ml="md" fz={10} color="dimmed">
@ -231,7 +238,10 @@ export const Tools: React.FC<{ isWidget?: boolean }> = ({ isWidget = false }) =>
</Menu.Item>
<Menu.Item
fz={12}
onClick={toggleFoldNodes}
onClick={() => {
toggleFoldNodes();
event({ action: "toggle_fold_nodes", category: "User", label: "Tools" });
}}
icon={foldNodes ? <CgArrowsShrinkH /> : <CgArrowsMergeAltH />}
rightSection={
<Text ml="md" fz={10} color="dimmed">
@ -243,7 +253,10 @@ export const Tools: React.FC<{ isWidget?: boolean }> = ({ isWidget = false }) =>
</Menu.Item>
<Menu.Item
fz={12}
onClick={toggleExpandCollapseGraph}
onClick={() => {
toggleExpandCollapseGraph();
event({ action: "toggle_collapse_nodes", category: "User", label: "Tools" });
}}
icon={graphCollapsed ? <VscExpandAll /> : <VscCollapseAll />}
rightSection={
<Text ml="md" fz={10} color="dimmed">

View File

@ -13,6 +13,7 @@ import {
Stack,
} from "@mantine/core";
import { toBlob, toPng, toSvg } from "html-to-image";
import { event } from "react-ga";
import toast from "react-hot-toast";
import { FiCopy, FiDownload } from "react-icons/fi";
@ -83,6 +84,7 @@ export const DownloadModal: React.FC<ModalProps> = ({ opened, onClose }) => {
toast.error("Failed to copy to clipboard");
} finally {
toast.dismiss("toastClipboard");
event({ action: "click_clipboard_image", category: "User" });
onClose();
}
};
@ -105,6 +107,7 @@ export const DownloadModal: React.FC<ModalProps> = ({ opened, onClose }) => {
toast.error("Failed to download image!");
} finally {
toast.dismiss("toastDownload");
event({ action: "click_download_image", category: "User" });
onClose();
}
};

View File

@ -1,8 +1,10 @@
import React from "react";
import type { AppProps } from "next/app";
import dynamic from "next/dynamic";
import { useRouter } from "next/router";
import { ThemeProvider } from "styled-components";
import { MantineProvider, MantineThemeOverride } from "@mantine/core";
import { pageview } from "react-ga";
import { monaSans } from "src/constants/customFonts";
import GlobalStyle from "src/constants/globalStyle";
import { lightTheme } from "src/constants/theme";
@ -20,6 +22,20 @@ const mantineTheme: MantineThemeOverride = {
};
function JsonCrack({ Component, pageProps }: AppProps) {
const router = useRouter();
React.useEffect(() => {
const handleRouteChange = (url: string) => {
pageview(url);
};
router.events.on("routeChangeComplete", handleRouteChange);
return () => {
router.events.off("routeChangeComplete", handleRouteChange);
};
}, [router.events]);
return (
<>
<GoogleAnalytics />

View File

@ -1,6 +1,7 @@
import debounce from "lodash.debounce";
import _get from "lodash.get";
import _set from "lodash.set";
import { event } from "react-ga";
import { toast } from "react-hot-toast";
import { create } from "zustand";
import { defaultJson } from "src/constants/data";
@ -105,6 +106,7 @@ const useFile = create<FileStates & JsonActions>()((set, get) => ({
const jsonContent = await jsonToContent(JSON.stringify(contentJson, null, 2), format);
get().setContents({ contents: jsonContent, hasChanges: false });
event({ action: "change_data_format", category: "User" });
} catch (error) {
get().clear();
console.info("The content was unable to be converted, so it was cleared instead.");

View File

@ -1,3 +1,4 @@
import { modalview } from "react-ga";
import { create } from "zustand";
import { Modal } from "src/containers/Modals";
import useUser from "./useUser";
@ -40,6 +41,7 @@ const useModal = create<ModalState & ModalActions>()(set => ({
return set({ premium: true });
}
if (visible) modalview(modal);
set({ [modal]: visible });
},
}));

View File

@ -1,4 +1,5 @@
import { setUser } from "@sentry/nextjs";
import { set as gaSet } from "react-ga";
import toast from "react-hot-toast";
import { create } from "zustand";
import { altogic } from "src/lib/api/altogic";
@ -57,7 +58,10 @@ const useUser = create<UserStates & UserActions>()(set => ({
toast.success("Logged out.");
useModal.setState({ account: false });
},
login: user => set({ user: user as unknown as User, isAuthenticated: true }),
login: user => {
set({ user: user as unknown as User, isAuthenticated: true });
gaSet({ userId: (user as User)._id });
},
checkSession: async () => {
if (isDevelopment) {
return set({ user: devUser as User, isAuthenticated: true, premium: true });
@ -84,6 +88,7 @@ const useUser = create<UserStates & UserActions>()(set => ({
premium: premiumData.premium,
premiumCancelled: premiumData?.status === "cancelled" || false,
});
gaSet({ userId: user._id });
} else if (new URLSearchParams(window.location.search).get("access_token")) {
const { errors, user } = await altogic.auth.getAuthGrant();
@ -97,6 +102,7 @@ const useUser = create<UserStates & UserActions>()(set => ({
setUser({ id: user._id, email: user.email, username: user.name });
set({ user: user as User, isAuthenticated: true, premium: premiumData.premium });
gaSet({ userId: user._id });
}
}
},

9
src/types/env.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
namespace NodeJS {
interface ProcessEnv {
NEXT_PUBLIC_BASE_URL: string;
NEXT_PUBLIC_ALTOGIC_ENV_URL: string;
NEXT_PUBLIC_ALTOGIC_CLIENT_KEY: string;
NEXT_PUBLIC_PAYMENT_URL: string;
NEXT_PUBLIC_GA_ID: string;
}
}

View File

@ -3719,6 +3719,11 @@ react-fast-compare@^3.2.0:
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49"
integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==
react-ga@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/react-ga/-/react-ga-3.3.1.tgz#d8e1f4e05ec55ed6ff944dcb14b99011dfaf9504"
integrity sha512-4Vc0W5EvXAXUN/wWyxvsAKDLLgtJ3oLmhYYssx+YzphJpejtOst6cbIHCIyF50Fdxuf5DDKqRYny24yJ2y7GFQ==
react-hot-toast@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-2.4.1.tgz#df04295eda8a7b12c4f968e54a61c8d36f4c0994"