Tracking A Game For Insight With Umami

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:

  1. game-start
  2. state-intro
  3. state-battle
  4. level-complete
  5. game-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.