From 8328a0d61a35e9797d58fe6e71d4ce3183cb4e5c Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Wed, 18 Feb 2026 18:21:21 +0000 Subject: [PATCH] fix: gdpr issue posthog + type improvements (#5392) --- apps/app-frontend/src/App.vue | 11 ++- apps/app-frontend/src/helpers/analytics.js | 24 ------- apps/app-frontend/src/helpers/analytics.ts | 80 ++++++++++++++++++++++ apps/app-frontend/src/store/install.js | 2 +- 4 files changed, 86 insertions(+), 31 deletions(-) delete mode 100644 apps/app-frontend/src/helpers/analytics.js create mode 100644 apps/app-frontend/src/helpers/analytics.ts diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index 1e497d924..f402277b6 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -77,7 +77,7 @@ import UpdateToast from '@/components/ui/UpdateToast.vue' import URLConfirmModal from '@/components/ui/URLConfirmModal.vue' import { useCheckDisableMouseover } from '@/composables/macCssFix.js' import { hide_ads_window, init_ads_window, show_ads_window } from '@/helpers/ads.js' -import { debugAnalytics, initAnalytics, optOutAnalytics, trackEvent } from '@/helpers/analytics' +import { debugAnalytics, initAnalytics, trackEvent } from '@/helpers/analytics' import { check_reachable } from '@/helpers/auth.js' import { get_user } from '@/helpers/cache.js' import { command_listener, warning_listener } from '@/helpers/events.js' @@ -271,12 +271,11 @@ async function setupApp() { isMaximized.value = await getCurrentWindow().isMaximized() }) - initAnalytics() - if (!telemetry) { - optOutAnalytics() + if (telemetry) { + initAnalytics() + if (dev) debugAnalytics() + trackEvent('Launched', { version, dev, onboarded }) } - if (dev) debugAnalytics() - trackEvent('Launched', { version, dev, onboarded }) if (!dev) document.addEventListener('contextmenu', (event) => event.preventDefault()) diff --git a/apps/app-frontend/src/helpers/analytics.js b/apps/app-frontend/src/helpers/analytics.js deleted file mode 100644 index 61b9de234..000000000 --- a/apps/app-frontend/src/helpers/analytics.js +++ /dev/null @@ -1,24 +0,0 @@ -import { posthog } from 'posthog-js' - -export const initAnalytics = () => { - posthog.init('phc_9Iqi6lFs9sr5BSqh9RRNRSJ0mATS9PSgirDiX3iOYJ', { - persistence: 'localStorage', - api_host: 'https://posthog.modrinth.com', - }) -} - -export const debugAnalytics = () => { - posthog.debug() -} - -export const optOutAnalytics = () => { - posthog.opt_out_capturing() -} - -export const optInAnalytics = () => { - posthog.opt_in_capturing() -} - -export const trackEvent = (eventName, properties) => { - posthog.capture(eventName, properties) -} diff --git a/apps/app-frontend/src/helpers/analytics.ts b/apps/app-frontend/src/helpers/analytics.ts new file mode 100644 index 000000000..770001be2 --- /dev/null +++ b/apps/app-frontend/src/helpers/analytics.ts @@ -0,0 +1,80 @@ +import { posthog } from 'posthog-js' + +interface InstanceProperties { + loader: string + game_version: string +} + +interface ProjectProperties extends InstanceProperties { + id: string + project_type: string +} + +type AnalyticsEventMap = { + Launched: { version: string; dev: boolean; onboarded: boolean } + PageView: { path: string; fromPath: string; failed: unknown } + InstanceCreate: { source: string } + InstanceCreateStart: { source: string } + InstancePlay: InstanceProperties & { source: string } + InstanceStop: Partial & { source?: string } + InstanceDuplicate: InstanceProperties + InstanceRepair: InstanceProperties + InstanceSetIcon: Record + InstanceRemoveIcon: Record + InstanceUpdateAll: InstanceProperties & { count: number; selected: boolean } + InstanceProjectUpdate: InstanceProperties & { id: string; name: string; project_type: string } + InstanceProjectDisable: InstanceProperties & { + id: string + name: string + project_type: string + disabled: boolean + } + InstanceProjectRemove: InstanceProperties & { id: string; name: string; project_type: string } + ProjectInstall: ProjectProperties & { version_id: string; title: string; source: string } + ProjectInstallStart: { source: string } + PackInstall: { id: string; version_id: string; title: string; source: string } + PackInstallStart: Record + AccountLogIn: { source?: string } + AccountLogOut: Record + JavaTest: { path: string; success: boolean } + JavaManualSelect: { version: string } + JavaAutoDetect: { path: string; version: string } +} + +export type AnalyticsEvent = keyof AnalyticsEventMap + +let initialized = false + +export const initAnalytics = () => { + if (initialized) return + posthog.init('phc_9Iqi6lFs9sr5BSqh9RRNRSJ0mATS9PSgirDiX3iOYJ', { + persistence: 'localStorage', + api_host: 'https://posthog.modrinth.com', + }) + initialized = true +} + +export const debugAnalytics = () => { + if (!initialized) return + posthog.debug() +} + +export const optOutAnalytics = () => { + if (!initialized) return + posthog.opt_out_capturing() +} + +export const optInAnalytics = () => { + initAnalytics() + posthog.opt_in_capturing() +} + +type OptionalArgs = Record extends T ? [properties?: T] : [properties: T] + +export const trackEvent = ( + eventName: E, + ...args: OptionalArgs +) => { + if (!initialized) return + posthog.capture(eventName, args[0]) +} diff --git a/apps/app-frontend/src/store/install.js b/apps/app-frontend/src/store/install.js index 8861bc4be..ad436f552 100644 --- a/apps/app-frontend/src/store/install.js +++ b/apps/app-frontend/src/store/install.js @@ -1,7 +1,7 @@ import dayjs from 'dayjs' import { defineStore } from 'pinia' -import { trackEvent } from '@/helpers/analytics.js' +import { trackEvent } from '@/helpers/analytics' import { get_project, get_version_many } from '@/helpers/cache.js' import { create_profile_and_install as packInstall } from '@/helpers/pack.js' import {