diff --git a/package.json b/package.json index 4e1a19d1..be24a933 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "dependencies": { "@friendofsvelte/tipex": "0.0.7", "md5": "^2.3.0", + "posthog-js": "^1.249.4", "svelte-persisted-store": "^0.12.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9e1e1436..16f61476 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: md5: specifier: ^2.3.0 version: 2.3.0 + posthog-js: + specifier: ^1.249.4 + version: 1.249.4 svelte-persisted-store: specifier: ^0.12.0 version: 0.12.0(svelte@5.28.2) @@ -751,6 +754,9 @@ packages: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} + core-js@3.42.0: + resolution: {integrity: sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==} + crelt@1.0.6: resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} @@ -844,6 +850,9 @@ packages: picomatch: optional: true + fflate@0.4.8: + resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -1138,6 +1147,20 @@ packages: resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} + posthog-js@1.249.4: + resolution: {integrity: sha512-Qq4cxDZ1P9BkwguuoVNTiLGQiET9vrzwjYWLS3DduKhRXqEzERLl9tOq2X8ZNPbo+D207+FILdWg/dTKUItfDg==} + peerDependencies: + '@rrweb/types': 2.0.0-alpha.17 + rrweb-snapshot: 2.0.0-alpha.17 + peerDependenciesMeta: + '@rrweb/types': + optional: true + rrweb-snapshot: + optional: true + + preact@10.26.8: + resolution: {integrity: sha512-1nMfdFjucm5hKvq0IClqZwK4FJkGXhRrQstOQ3P4vp8HxKrJEMFcY6RdBRVTdfQS/UlnX6gfbPuTvaqx/bDoeQ==} + prettier-plugin-svelte@3.3.3: resolution: {integrity: sha512-yViK9zqQ+H2qZD1w/bH7W8i+bVfKrD8GIFjkFe4Thl6kCT9SlAsXVNmt3jCvQOCsnOhcvYgsoVlRV/Eu6x5nNw==} peerDependencies: @@ -1521,6 +1544,9 @@ packages: w3c-keyname@2.2.8: resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + web-vitals@4.2.4: + resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -2117,6 +2143,8 @@ snapshots: cookie@0.6.0: {} + core-js@3.42.0: {} + crelt@1.0.6: {} cross-spawn@7.0.6: @@ -2211,6 +2239,8 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fflate@0.4.8: {} + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -2463,6 +2493,15 @@ snapshots: picocolors: 1.1.1 source-map-js: 1.2.1 + posthog-js@1.249.4: + dependencies: + core-js: 3.42.0 + fflate: 0.4.8 + preact: 10.26.8 + web-vitals: 4.2.4 + + preact@10.26.8: {} + prettier-plugin-svelte@3.3.3(prettier@3.5.3)(svelte@5.28.2): dependencies: prettier: 3.5.3 @@ -2851,6 +2890,8 @@ snapshots: w3c-keyname@2.2.8: {} + web-vitals@4.2.4: {} + which@2.0.2: dependencies: isexe: 2.0.0 diff --git a/src/hooks.client.ts b/src/hooks.client.ts new file mode 100644 index 00000000..9803f880 --- /dev/null +++ b/src/hooks.client.ts @@ -0,0 +1,8 @@ +import posthog from 'posthog-js'; +import type { HandleClientError } from '@sveltejs/kit'; + +export const handleError: HandleClientError = ({ error, status }) => { + if (status !== 404) { + posthog.captureException(error); + } +}; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index f700ac9d..19822874 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -20,12 +20,22 @@ import { goto } from '$app/navigation'; import { onMount } from 'svelte'; + import posthog from 'posthog-js'; + import { browser } from '$app/environment'; + onMount(() => { const urlParams = new URLSearchParams(window.location.search); if (urlParams.get('experimental') === 'true') { $preferencesStore.experimentalFeatures = true; goto('/'); } + if (browser) { + posthog.init('phc_jg4gOdigfHQD4MSgrSaO883dp2LjNJbJO7azv61UtI0', { + api_host: 'https://us.i.posthog.com', + person_profiles: 'always', + capture_exceptions: true + }); + } });