# How Video Tracking Works
*FlanneryAllen/codetrails@main · investigation · 5 markers*

> **Entry point.** User plays a video; the `VideoPlayer` component's HTML5 event listeners capture `play`, `pause`, and `timeupdate` events.
>
> **State tracking.** The `useVideoTracking` hook maintains refs for timing and deduplication, transforming DOM events into analytics calls.
>
> **Dispatch.** Track functions package event metadata and call `core.event()`, which routes to both server-side journey tracking and client-side Google Analytics 4.

**Author:** Julie Allen · **Updated:** 2026-05-29T19:32:18.164Z

## Markers
1. **User plays video** — _(no file)_
   User interacts with an HTML5 video element. The browser fires native `play`, `pause`, `timeupdate`, `ended`, and `seeked` events that the `VideoPlayer` component listens for.
2. **VideoPlayer component captures events** — `landing-page-demo/src/components/VideoPlayer.tsx:26–72`
   The `VideoPlayer` component registers event listeners on the video ref and delegates to the `useVideoTracking` hook. The hook provides `handlePlay`, `handlePause`, and `handleTimeUpdate` callbacks that wrap the raw DOM events with tracking metadata (video ID, title, duration, timestamps).
3. **Hook tracks play, progress, and pause** — `landing-page-demo/src/lib/analytics/hooks/useVideoTracking.ts:20–58` _(subject)_
   The `useVideoTracking` hook maintains three refs: `playStartTimeRef` (captures when play begins to calculate actual watch duration), `lastProgressRef` (tracks the highest milestone hit to prevent duplicate events), and `hasCompletedRef` (ensures completion fires once). On `timeupdate`, it checks for milestone thresholds [25%, 50%, 75%, 90%] and completion at 95% (not 100% to handle browser playback variations). Each event type calls the corresponding track function.
4. **Track functions package events** — `landing-page-demo/src/lib/analytics/video.ts:9–91`
   Five track functions (`trackVideoPlay`, `trackVideoPause`, `trackVideoProgress`, `trackVideoComplete`, `trackVideoError`) package events with video-specific metadata: `video_id`, `video_title`, `progress_percent`, `watch_duration`, `milestone`, etc. Each calls the core `event()` function to dispatch.
5. **Core dispatches to analytics systems** — `landing-page-demo/src/lib/analytics/core.ts:87–146`
   The central event dispatcher routes to server-side tracking via `trackServerEvent` (journey session manager, persistence) when `isServerSideEnabled()` is true, and to client-side Google Analytics 4 via `window.gtag('event', action, params)` when `isClientSideEnabled()` and gtag is available. Failed events are queued for retry via `getEventQueue().enqueue()`.

---
Interactive view: https://app.principal-ade.com/trail/f191756b-616a-4a9d-b3fb-84fc0bacf642
JSON: https://app.principal-ade.com/api/trails/by-id/f191756b-616a-4a9d-b3fb-84fc0bacf642
Authored at `ebd2e938b59dddfd1eb03e85f98ac10d79641cb5` (main).
To open a trail or tour locally in the interactive viewer, see https://app.principal-ade.com for the Principal CLI quickstart.
