feat(web): add privacy-friendly Umami custom events
Instrument the play flow with 9 content-free custom events (game_start, art_style_select, style_image_upload, scene_reached, choice_select, vision_click, tts_toggle, fullscreen_toggle, play_heartbeat) to measure retention, engagement depth and session duration. Privacy is enforced by construction, not convention: - lib/analytics.ts types each event with a discriminated union, so a payload has no slot for free text — prompts, world guides, uploaded images and vision output can never reach analytics (compile-time guarantee, not a comment). - track() no-ops without window.umami and never throws into the app. - coarse 30s heartbeat fires only while the tab is visible. - script stays gated on NEXT_PUBLIC_UMAMI_* env (blank → no script), honours Do-Not-Track, and locks to an exact data-domains allowlist. - one-line on-site disclosure with a link, shown only when tracking is on. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+13
-2
@@ -73,7 +73,18 @@ NEXT_PUBLIC_IMAGE_PROXY_URL=
|
||||
# NEXT_PUBLIC_UMAMI_SRC=https://cloud.umami.is/script.js
|
||||
# Self-host later: point SRC at your own instance — the integration is identical
|
||||
# (no code change), e.g. NEXT_PUBLIC_UMAMI_SRC=https://stats.example.com/script.js
|
||||
# Both blank → no script is injected (zero tracking). NEXT_PUBLIC_ vars are
|
||||
# inlined at BUILD time, so set them in the build env (Vercel project settings).
|
||||
# Both blank → no script is injected (zero tracking; every track() call no-ops).
|
||||
# Beyond page views the app emits content-free custom events (game start, scene
|
||||
# reached, choice picked, ...) — only enums/counts/booleans, never your prompts,
|
||||
# uploaded images or any per-user ID. The visitor's Do-Not-Track is honoured.
|
||||
# NEXT_PUBLIC_ vars are inlined at BUILD time, so set them in the build env
|
||||
# (Vercel project settings).
|
||||
NEXT_PUBLIC_UMAMI_SRC=
|
||||
NEXT_PUBLIC_UMAMI_WEBSITE_ID=
|
||||
|
||||
# Optional hostname allowlist — defense-in-depth on top of the blank-to-disable
|
||||
# gate above. The tracker fires only when window.location.hostname EXACTLY
|
||||
# matches an entry, so a fork that copied these vars stays silent on its own
|
||||
# domain. Comma-separated, exact match: apex ≠ www (list both), no wildcards.
|
||||
# Blank → track on all hosts. e.g. infiplot.com,www.infiplot.com
|
||||
NEXT_PUBLIC_UMAMI_DOMAINS=
|
||||
|
||||
Reference in New Issue
Block a user