Mental Model
For games, the best practice in Umami is:
Track state transitions as events, not page views.
Because:
- It’s a SPA-like structure
- No full reloads
- One URL represents many states
- We care about flow, not reloads
Best Tracking Architecture
Track Game Start
When game loads:
umami.track('game-start', {
game: 'Blue-Soaring-Phoenix'
});
The game names are currently random
Track State Transitions
Every time your state machine changes state:
umami.track('state-change', {
game: 'Blue-Soaring-Phoenix',
from: previousState,
to: currentState
});
Or even better:
umami.track(`state-${currentState}`, {
game: 'Blue-Soaring-Phoenix'
});
Now each state becomes measurable.
Track Important Events
Examples:
umami.track('level-complete', {
game: 'Blue-Soaring-Phoenix',
level: 3
});
umami.track('player-death', {
game: 'Blue-Soaring-Phoenix',
state: currentState
});
umami.track('game-finished', {
game: 'Blue-Soaring-Phoenix'
});
How To Build Funnels From This
Example funnel:
game-startstate-introstate-battlelevel-completegame-finished
This tells you:
- Where players drop off
- Which states are bottlenecks
- Which states cause rage quit
- Conversion from start → finish
Advanced (Recommended)
Since you are using:
/screen/{game-id}
You should:
Extract game ID dynamically
const gameId = window.location.pathname.split('/').pop();
umami.track('game-start', { game: gameId });
Now your tracking automatically works for all games.
Even Better: Track State Duration
Add timestamps:
let stateEnterTime = Date.now();
function onStateChange(newState) {
const duration = Date.now() - stateEnterTime;
umami.track('state-duration', {
game: gameId,
state: previousState,
duration: duration
});
stateEnterTime = Date.now();
}
The Cleanest Structure For tracking?
Given your architecture, I would track:
| Event | When |
|---|---|
| game-start | Initial load |
| state-enter | Every state transition |
| state-exit | Optional |
| game-finished | Win |
| game-abandoned | On unload (optional) |
Goals
Information I want:
- Which states take too long
- Which states are skipped
- Engagement level
- Reconstruct full player paths, when do they fall off
- Detect loops
- Identify impossible transitions
- Find stuck states
I Do NOT want:
- Track every tiny UI action
- Track animations
- Track every frame
As this will flood our analytics.
Track:
- Meaningful transitions
- Player intent
- Milestones
Open questions
- Do we want per-session tracking or anonymous only?
- What are the benefits of each approach?
- GDPR considerations.
Our Engineering Perspective: High Insight, Low Overhead
As we refine our tracking architecture for the game, our goal is to maximize the signal-to-noise ratio. We want to know exactly how players experience the game without bloating the client-side logic or flooding our database with trivial UI events.
1. Minimal Code Overhead via State Machine Hooks
Since the game already operates on a formal state machine, we don't need to sprinkle umami.track calls throughout our UI components. Instead, we hook directly into the state transition logic. One single function call in the state machine's entry/exit handler covers the entire application. This keeps our domain logic clean and our tracking centralized.
2. Strategic Session Tracking vs. Pure Anonymity
We discussed the tradeoff between session-based and anonymous tracking.
- Anonymous (Default): Great for counting total events and seeing broad trends. This is our baseline and is 100% GDPR compliant out of the box because no PII or persistent identifiers are stored.
- Session-Based: By utilizing Umami's built-in session handling (which uses a rotating hash based on IP, User Agent, and Website ID), we can reconstruct a single player's journey through the states without actually identifying who they are. This is the "sweet spot" for us: it allows funnel analysis (Start → Level 1 → Finish) while remaining privacy-first. We aren't tracking people; we are tracking journeys.
3. "Journey Replay" without the Data Weight
Instead of complex session recording tools, we use these events to build a "breadcrumb trail." If we see a high frequency of state-enter events for the same session without a corresponding game-finished, we've identified a drop-off point. If we see a session looping between two states, we've found a UX friction point or a bug.
4. GDPR by Design
By hosting our own Umami instance and stripping out PII before it ever hits the wire, we ensure that our player data never leaves our infrastructure. Our "we" approach means we own the data, the tracking logic, and the responsibility to keep it anonymous.
Summary of our tracking strategy:
- Hook the State Machine: Zero UI-level boilerplate.
- Track Journeys, not Users: Leverage Umami's anonymous session hashes.
- Signal over Noise: Focus on state transitions and milestones to keep the data actionable.