fix: defer PostHog/Sentry loading until user consents to telemetry

PostHog SDK was initialized on app mount based only on the server-level
config flag, ignoring user consent. This caused network requests to
us-assets.i.posthog.com (config.js, web-vitals.js, dead-clicks-autocapture.js)
even when the user had not opted in or had explicitly declined telemetry.

- Replace static imports of posthog-js and @sentry/react with dynamic
  import() so the SDK bundles are not downloaded until consent is granted
- Gate initAnalytics on analyticsConsent.analyticsEnabled === true,
  not just server config.enabled
- Add consent re-check after each await import() to handle revocation
  during the async load
- Add shutdownAnalytics() that calls opt_out_capturing() + reset()
  for mid-session consent revocation
- setAnalyticsConsent(false) now triggers full SDK shutdown automatically
- Rewrite analytics test suite with 44 tests covering init gating,
  shutdown lifecycle, consent toggle, race conditions, and Sentry callbacks

Closes #98
This commit is contained in:
SnapOtter
2026-04-29 14:16:38 +08:00
parent 03f82567d0
commit 4d3e5e9c02
4 changed files with 377 additions and 195 deletions
+7 -10
View File
@@ -173,12 +173,6 @@ export function App() {
fetchAnalyticsConfig();
}, [fetchAnalyticsConfig]);
useEffect(() => {
if (analyticsConfigLoaded && analyticsConfig?.enabled) {
initAnalytics(analyticsConfig);
}
}, [analyticsConfigLoaded, analyticsConfig]);
useEffect(() => {
if (
!analyticsConfigLoaded ||
@@ -186,10 +180,13 @@ export function App() {
analyticsConsent.analyticsEnabled !== true
)
return;
identify(analyticsConfig.instanceId, {
$set: { version: APP_VERSION },
$set_once: { instance_id: analyticsConfig.instanceId },
});
void (async () => {
await initAnalytics(analyticsConfig);
identify(analyticsConfig.instanceId, {
$set: { version: APP_VERSION },
$set_once: { instance_id: analyticsConfig.instanceId },
});
})();
}, [analyticsConfigLoaded, analyticsConfig, analyticsConsent.analyticsEnabled]);
return (