Analytics now works even if blocked by tracker blockers

This commit is contained in:
DrMint 2022-08-28 20:57:40 +02:00
parent c73e6a0bb4
commit 0453a83d2f
11 changed files with 89 additions and 72 deletions

View File

@ -172,9 +172,9 @@
"anchor_link_copied": "Copied! 👍",
"folders": "Folders",
"empty_folder_message": "This folder is empty",
"switch_to_grid_view": null,
"switch_to_folder_view": null,
"content_is_not_available": null
"switch_to_grid_view": "Switch to grid view",
"switch_to_folder_view": "Switch to folder view",
"content_is_not_available": "This content is not available"
}
},
{

View File

@ -22,6 +22,7 @@ import { OpenGraph, TITLE_PREFIX, TITLE_SEPARATOR } from "helpers/openGraph";
import { useIs1ColumnLayout, useIsScreenAtLeast } from "hooks/useContainerQuery";
import { useOnResize } from "hooks/useOnResize";
import { Ids } from "types/ids";
import { sendAnalytics } from "helpers/analytics";
/*
*
@ -324,7 +325,7 @@ export const AppLayout = ({
className="mt-8"
onClick={() => {
disgardSafariWarning();
umami("[Safari] Disgard warning");
sendAnalytics("Safari", "Disgard warning");
}}
/>
</Popup>
@ -333,7 +334,7 @@ export const AppLayout = ({
state={configPanelOpen}
onClose={() => {
setConfigPanelOpen(false);
umami("[Settings] Close settings");
sendAnalytics("Settings", "Close settings");
}}>
<h2 className="text-2xl">{langui.settings}</h2>
@ -364,7 +365,7 @@ export const AppLayout = ({
onChange={(items) => {
const newPreferredLanguages = items.map((item) => item.code);
setPreferredLanguages(newPreferredLanguages);
umami("[Settings] Change preferred languages");
sendAnalytics("Settings", "Change preferred languages");
}}
/>
)}
@ -383,7 +384,7 @@ export const AppLayout = ({
onClick: () => {
setDarkMode(false);
setSelectedThemeMode(true);
umami("[Settings] Change theme (light)");
sendAnalytics("Settings", "Change theme (light)");
},
active: selectedThemeMode && !darkMode,
text: langui.light,
@ -391,7 +392,7 @@ export const AppLayout = ({
{
onClick: () => {
setSelectedThemeMode(false);
umami("[Settings] Change theme (auto)");
sendAnalytics("Settings", "Change theme (auto)");
},
active: !selectedThemeMode,
text: langui.auto,
@ -400,7 +401,7 @@ export const AppLayout = ({
onClick: () => {
setDarkMode(true);
setSelectedThemeMode(true);
umami("[Settings] Change theme (dark)");
sendAnalytics("Settings", "Change theme (dark)");
},
active: selectedThemeMode && darkMode,
text: langui.dark,
@ -417,7 +418,10 @@ export const AppLayout = ({
value={currencySelect}
onChange={(newCurrency) => {
setCurrencySelect(newCurrency);
umami(`[Settings] Change currency (${currencyOptions[newCurrency]})}`);
sendAnalytics(
"Settings",
`Change currency (${currencyOptions[newCurrency]})}`
);
}}
className="w-28"
/>
@ -431,13 +435,11 @@ export const AppLayout = ({
{
onClick: () => {
setFontSize((current) => current / 1.05);
umami(
`[Settings] Change font size (${((fontSize / 1.05) * 100).toLocaleString(
undefined,
{
maximumFractionDigits: 0,
}
)}%)`
sendAnalytics(
"Settings",
`Change font size (${((fontSize / 1.05) * 100).toLocaleString(undefined, {
maximumFractionDigits: 0,
})}%)`
);
},
icon: Icon.TextDecrease,
@ -445,7 +447,7 @@ export const AppLayout = ({
{
onClick: () => {
setFontSize(1);
umami("[Settings] Change font size (100%)");
sendAnalytics("Settings", "Change font size (100%)");
},
text: `${(fontSize * 100).toLocaleString(undefined, {
maximumFractionDigits: 0,
@ -454,13 +456,11 @@ export const AppLayout = ({
{
onClick: () => {
setFontSize((current) => current * 1.05);
umami(
`[Settings] Change font size (${(fontSize * 1.05 * 100).toLocaleString(
undefined,
{
maximumFractionDigits: 0,
}
)}%)`
sendAnalytics(
"Settings",
`Change font size (${(fontSize * 1.05 * 100).toLocaleString(undefined, {
maximumFractionDigits: 0,
})}%)`
);
},
icon: Icon.TextIncrease,
@ -476,7 +476,7 @@ export const AppLayout = ({
active={!dyslexic}
onClick={() => {
setDyslexic(false);
umami("[Settings] Change font (Zen Maru Gothic)");
sendAnalytics("Settings", "Change font (Zen Maru Gothic)");
}}
className="font-zenMaruGothic"
text="Zen Maru Gothic"
@ -485,7 +485,7 @@ export const AppLayout = ({
active={dyslexic}
onClick={() => {
setDyslexic(true);
umami("[Settings] Change font (OpenDyslexic)");
sendAnalytics("Settings", "Change font (OpenDyslexic)");
}}
className="font-openDyslexic"
text="OpenDyslexic"
@ -501,7 +501,7 @@ export const AppLayout = ({
value={playerName}
onChange={(newName) => {
setPlayerName(newName);
umami("[Settings] Change username");
sendAnalytics("Settings", "Change username");
}}
/>
</div>

View File

@ -6,6 +6,7 @@ import { cJoin } from "helpers/className";
import { prettyLanguage } from "helpers/formatters";
import { iterateMap } from "helpers/others";
import { useLanguages } from "hooks/useLocalData";
import { sendAnalytics } from "helpers/analytics";
/*
*
@ -42,7 +43,7 @@ export const LanguageSwitcher = ({
active={value === localesIndex}
onClick={() => {
onLanguageChanged(value);
umami(`[Language Switcher] Switch language (${locale})`);
sendAnalytics("Language Switcher", `Switch language (${locale})`);
}}
text={prettyLanguage(locale, languages)}
/>

View File

@ -9,6 +9,7 @@ import { cIf, cJoin } from "helpers/className";
import { isDefinedAndNotEmpty } from "helpers/others";
import { Link } from "components/Inputs/Link";
import { useIs3ColumnsLayout } from "hooks/useContainerQuery";
import { sendAnalytics } from "helpers/analytics";
/*
*
@ -40,9 +41,9 @@ export const MainPanel = (): JSX.Element => {
<Button
onClick={() => {
if (mainPanelReduced) {
umami("[MainPanel] Expand");
sendAnalytics("MainPanel", "Expand");
} else {
umami("[MainPanel] Reduce");
sendAnalytics("MainPanel", "Reduce");
}
toggleMainPanelReduced();
}}
@ -81,7 +82,7 @@ export const MainPanel = (): JSX.Element => {
<Button
onClick={() => {
setConfigPanelOpen(true);
umami("[Settings] Open settings");
sendAnalytics("Settings", "Open settings");
}}
icon={Icon.Settings}
/>
@ -173,7 +174,7 @@ export const MainPanel = (): JSX.Element => {
)}
<div className="mt-4 mb-8 grid place-content-center">
<a
onClick={() => umami("[MainPanel] Visit license")}
onClick={() => sendAnalytics("MainPanel", "Visit license")}
aria-label="Read more about the license we use for this website"
className="group grid grid-flow-col place-content-center gap-1 transition-[filter]"
href="https://creativecommons.org/licenses/by-sa/4.0/">
@ -202,7 +203,7 @@ export const MainPanel = (): JSX.Element => {
<div className="mt-12 mb-4 grid h-4 grid-flow-col place-content-center gap-8">
<a
aria-label="Browse our GitHub repository, which include this website source code"
onClick={() => umami("[MainPanel] Visit GitHub")}
onClick={() => sendAnalytics("MainPanel", "Visit GitHub")}
className="aspect-square w-10
bg-black transition-colors [mask:url('/icons/github-brands.svg')]
![mask-size:contain] ![mask-repeat:no-repeat] ![mask-position:center] hover:bg-dark"
@ -211,7 +212,7 @@ export const MainPanel = (): JSX.Element => {
rel="noopener noreferrer"></a>
<a
aria-label="Follow us on Twitter"
onClick={() => umami("[MainPanel] Visit Twitter")}
onClick={() => sendAnalytics("MainPanel", "Visit Twitter")}
className="aspect-square w-10
bg-black transition-colors [mask:url('/icons/twitter-brands.svg')]
![mask-size:contain] ![mask-repeat:no-repeat] ![mask-position:center] hover:bg-dark"
@ -220,7 +221,7 @@ export const MainPanel = (): JSX.Element => {
rel="noopener noreferrer"></a>
<a
aria-label="Join our Discord server!"
onClick={() => umami("[MainPanel] Visit Discord")}
onClick={() => sendAnalytics("MainPanel", "Visit Discord")}
className="aspect-square w-10
bg-black transition-colors [mask:url('/icons/discord-brands.svg')]
![mask-size:contain] ![mask-repeat:no-repeat] ![mask-position:center] hover:bg-dark"

7
src/helpers/analytics.ts Normal file
View File

@ -0,0 +1,7 @@
export const sendAnalytics = (category: string, event: string): void => {
try {
umami(`[${category}] ${event}`);
} catch (error) {
console.log(error);
}
};

View File

@ -8,6 +8,7 @@ import { randomInt } from "helpers/numbers";
import { RequestMailProps, ResponseMailProps } from "pages/api/mail";
import { useIs1ColumnLayout } from "hooks/useContainerQuery";
import { useAppLayout } from "contexts/AppLayoutContext";
import { sendAnalytics } from "helpers/analytics";
/*
*
@ -66,19 +67,19 @@ const AboutUs = (props: PostStaticProps): JSX.Element => {
case "OKAY":
setFormResponse(langui.response_email_success ?? "");
setFormState("completed");
umami("[Contact] Send email (success)");
sendAnalytics("Contact", "Send email (success)");
break;
case "EENVELOPE":
setFormResponse(langui.response_invalid_email ?? "");
setFormState("stale");
umami("[Contact] Send email (invalid email)");
sendAnalytics("Contact", "Send email (invalid email)");
break;
default:
setFormResponse(response.message ?? "");
setFormState("stale");
umami("[Contact] Send email (error)");
sendAnalytics("Contact", "Send email (error)");
break;
}
});

View File

@ -26,6 +26,7 @@ import { useIsContentPanelAtLeast } from "hooks/useContainerQuery";
import { cJoin, cIf } from "helpers/className";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
import { sendAnalytics } from "helpers/analytics";
/*
*
@ -137,9 +138,9 @@ const Contents = ({ contents, ...otherProps }: Props): JSX.Element => {
onChange={(name) => {
setSearchName(name);
if (isDefinedAndNotEmpty(name)) {
umami("[Contents/All] Change search term");
sendAnalytics("Contents/All", "Change search term");
} else {
umami("[Contents/All] Clear search term");
sendAnalytics("Contents/All", "Clear search term");
}
}}
/>
@ -151,8 +152,9 @@ const Contents = ({ contents, ...otherProps }: Props): JSX.Element => {
value={groupingMethod}
onChange={(value) => {
setGroupingMethod(value);
umami(
`[Contents/All] Change grouping method (${["none", "category", "type"][value + 1]})`
sendAnalytics(
"Contents/All",
`Change grouping method (${["none", "category", "type"][value + 1]})`
);
}}
allowEmpty
@ -165,7 +167,7 @@ const Contents = ({ contents, ...otherProps }: Props): JSX.Element => {
value={keepInfoVisible}
onClick={() => {
toggleKeepInfoVisible();
umami(`[Contents/All] Always ${keepInfoVisible ? "hide" : "show"} info`);
sendAnalytics("Contents/All", `Always ${keepInfoVisible ? "hide" : "show"} info`);
}}
/>
</WithLabel>
@ -179,7 +181,7 @@ const Contents = ({ contents, ...otherProps }: Props): JSX.Element => {
setSearchName(DEFAULT_FILTERS_STATE.searchName);
setGroupingMethod(DEFAULT_FILTERS_STATE.groupingMethod);
setKeepInfoVisible(DEFAULT_FILTERS_STATE.keepInfoVisible);
umami("[Contents/All] Reset all filters");
sendAnalytics("Contents/All", "Reset all filters");
}}
/>
</SubPanel>

View File

@ -33,6 +33,7 @@ import { useIsContentPanelAtLeast } from "hooks/useContainerQuery";
import { cIf, cJoin } from "helpers/className";
import { useCurrencies } from "hooks/useLocalData";
import { getLangui } from "graphql/fetchLocalData";
import { sendAnalytics } from "helpers/analytics";
/*
*
@ -238,9 +239,9 @@ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
onChange={(name) => {
setSearchName(name);
if (isDefinedAndNotEmpty(name)) {
umami("[Library] Change search term");
sendAnalytics("Library", "Change search term");
} else {
umami("[Library] Clear search term");
sendAnalytics("Library", "Clear search term");
}
}}
/>
@ -256,10 +257,9 @@ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
value={groupingMethod}
onChange={(value) => {
setGroupingMethod(value);
umami(
`[Library] Change grouping method (${
["none", "category", "type", "year"][value + 1]
})`
sendAnalytics(
"Library",
`Change grouping method (${["none", "category", "type", "year"][value + 1]})`
);
}}
allowEmpty
@ -277,8 +277,9 @@ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
value={sortingMethod}
onChange={(value) => {
setSortingMethod(value);
umami(
`[Library] Change sorting method (${["name", "price", "release date"][value]})`
sendAnalytics(
"Library",
`Change sorting method (${["name", "price", "release date"][value]})`
);
}}
/>
@ -289,7 +290,7 @@ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
value={showSubitems}
onClick={() => {
toggleShowSubitems();
umami(`[Library] ${showSubitems ? "Hide" : "Show"} subitems`);
sendAnalytics("Library", `${showSubitems ? "Hide" : "Show"} subitems`);
}}
/>
</WithLabel>
@ -299,7 +300,7 @@ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
value={showPrimaryItems}
onClick={() => {
toggleShowPrimaryItems();
umami(`[Library] ${showPrimaryItems ? "Hide" : "Show"} primary items`);
sendAnalytics("Library", `${showPrimaryItems ? "Hide" : "Show"} primary items`);
}}
/>
</WithLabel>
@ -309,7 +310,7 @@ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
value={showSecondaryItems}
onClick={() => {
toggleShowSecondaryItems();
umami(`[Library] ${showSecondaryItems ? "Hide" : "Show"} secondary items`);
sendAnalytics("Library", `${showSecondaryItems ? "Hide" : "Show"} secondary items`);
}}
/>
</WithLabel>
@ -320,7 +321,7 @@ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
value={keepInfoVisible}
onClick={() => {
toggleKeepInfoVisible();
umami(`[Library] Always ${keepInfoVisible ? "hide" : "show"} info`);
sendAnalytics("Library", `Always ${keepInfoVisible ? "hide" : "show"} info`);
}}
/>
</WithLabel>
@ -334,7 +335,7 @@ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
icon: Icon.Favorite,
onClick: () => {
setFilterUserStatus(LibraryItemUserStatus.Want);
umami("[Library] Set filter status (I want)");
sendAnalytics("Library", "Set filter status (I want)");
},
active: filterUserStatus === LibraryItemUserStatus.Want,
},
@ -343,7 +344,7 @@ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
icon: Icon.BackHand,
onClick: () => {
setFilterUserStatus(LibraryItemUserStatus.Have);
umami("[Library] Set filter status (I have)");
sendAnalytics("Library", "Set filter status (I have)");
},
active: filterUserStatus === LibraryItemUserStatus.Have,
},
@ -352,7 +353,7 @@ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
icon: Icon.RadioButtonUnchecked,
onClick: () => {
setFilterUserStatus(LibraryItemUserStatus.None);
umami("[Library] Set filter status (unmarked)");
sendAnalytics("Library", "Set filter status (unmarked)");
},
active: filterUserStatus === LibraryItemUserStatus.None,
},
@ -361,7 +362,7 @@ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
text: langui.all,
onClick: () => {
setFilterUserStatus(undefined);
umami("[Library] Set filter status (all)");
sendAnalytics("Library", "Set filter status (all)");
},
active: isUndefined(filterUserStatus),
},
@ -381,7 +382,7 @@ const Library = ({ items, ...otherProps }: Props): JSX.Element => {
setGroupingMethod(DEFAULT_FILTERS_STATE.groupingMethod);
setKeepInfoVisible(DEFAULT_FILTERS_STATE.keepInfoVisible);
setFilterUserStatus(DEFAULT_FILTERS_STATE.filterUserStatus);
umami("[Library] Reset all filters");
sendAnalytics("Library", "Reset all filters");
}}
/>
</SubPanel>

View File

@ -24,6 +24,7 @@ import { cIf } from "helpers/className";
import { useIsContentPanelAtLeast } from "hooks/useContainerQuery";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
import { sendAnalytics } from "helpers/analytics";
/*
*
@ -69,9 +70,9 @@ const News = ({ posts, ...otherProps }: Props): JSX.Element => {
onChange={(name) => {
setSearchName(name);
if (isDefinedAndNotEmpty(name)) {
umami("[News] Change search term");
sendAnalytics("News", "Change search term");
} else {
umami("[News] Clear search term");
sendAnalytics("News", "Clear search term");
}
}}
/>
@ -82,7 +83,7 @@ const News = ({ posts, ...otherProps }: Props): JSX.Element => {
value={keepInfoVisible}
onClick={() => {
toggleKeepInfoVisible();
umami(`[News] Always ${keepInfoVisible ? "hide" : "show"} info`);
sendAnalytics("News", `Always ${keepInfoVisible ? "hide" : "show"} info`);
}}
/>
</WithLabel>
@ -95,7 +96,7 @@ const News = ({ posts, ...otherProps }: Props): JSX.Element => {
onClick={() => {
setSearchName(DEFAULT_FILTERS_STATE.searchName);
setKeepInfoVisible(DEFAULT_FILTERS_STATE.keepInfoVisible);
umami("[News] Reset all filters");
sendAnalytics("News", "Reset all filters");
}}
/>
</SubPanel>

View File

@ -26,6 +26,7 @@ import { useIsContentPanelAtLeast } from "hooks/useContainerQuery";
import { cIf } from "helpers/className";
import { useAppLayout } from "contexts/AppLayoutContext";
import { getLangui } from "graphql/fetchLocalData";
import { sendAnalytics } from "helpers/analytics";
/*
*
@ -82,9 +83,9 @@ const Wiki = ({ pages, ...otherProps }: Props): JSX.Element => {
onChange={(name) => {
setSearchName(name);
if (isDefinedAndNotEmpty(name)) {
umami("[Wiki] Change search term");
sendAnalytics("Wiki", "Change search term");
} else {
umami("[Wiki] Clear search term");
sendAnalytics("Wiki", "Clear search term");
}
}}
/>
@ -96,7 +97,7 @@ const Wiki = ({ pages, ...otherProps }: Props): JSX.Element => {
value={groupingMethod}
onChange={(value) => {
setGroupingMethod(value);
umami(`[Wiki] Change grouping method (${["none", "category"][value + 1]})`);
sendAnalytics("Wiki", `Change grouping method (${["none", "category"][value + 1]})`);
}}
allowEmpty
/>
@ -108,7 +109,7 @@ const Wiki = ({ pages, ...otherProps }: Props): JSX.Element => {
value={keepInfoVisible}
onClick={() => {
toggleKeepInfoVisible();
umami(`[Wiki] Always ${keepInfoVisible ? "hide" : "show"} info`);
sendAnalytics("Wiki", `Always ${keepInfoVisible ? "hide" : "show"} info`);
}}
/>
</WithLabel>
@ -122,7 +123,7 @@ const Wiki = ({ pages, ...otherProps }: Props): JSX.Element => {
setSearchName(DEFAULT_FILTERS_STATE.searchName);
setGroupingMethod(DEFAULT_FILTERS_STATE.groupingMethod);
setKeepInfoVisible(DEFAULT_FILTERS_STATE.keepInfoVisible);
umami("[Wiki] Reset all filters");
sendAnalytics("Wiki", "Reset all filters");
}}
/>

View File

@ -1,5 +1,7 @@
export {};
type Umami = (eventName: string) => void;
declare global {
function umami(eventName: string): void;
const umami: Umami;
}