feat(analytics): add video analytics pipeline with ingest server, event tracking, and ClickHouse schema#3
Open
aman051197 wants to merge 21 commits into
Open
feat(analytics): add video analytics pipeline with ingest server, event tracking, and ClickHouse schema#3aman051197 wants to merge 21 commits into
aman051197 wants to merge 21 commits into
Conversation
…nt tracking, and ClickHouse schema
…ack first view load
…g in analytics tracker
…in PresentUpcoming component
… player adapter to prevent unintended pause events
…d transport layer improvements
…d size-based flush trigger
…n_fix Enhance analytics tracking with custom dimensions and transport improvements
There was a problem hiding this comment.
Pull request overview
This PR introduces a new client-side analytics pipeline for the ImageKit Video Player (event tracking → batching → wire-format encoding → ingest transport), wires it into the player plugin behind an analytics.enabled flag, and adjusts playlist thumbnail handling to avoid mutating shared source objects.
Changes:
- Added an analytics subsystem (types, state machine, Video.js adapter, batching/transport, v1 wire format).
- Integrated analytics initialization into the core player plugin + added
analyticsoptions to the publicIKPlayerOptions. - Updated playlist thumbnail generation to avoid mutating the original playlist/source objects when applying default poster transformations.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/video-player/javascript/modules/playlist/thumbnail.ts | Avoids mutating shared playlist item state when preparing poster thumbnails (but needs a prepared null-guard fix). |
| packages/video-player/javascript/modules/playlist/present-upcoming.ts | Clones playlist items before applying default poster transformation for “Next up” UI. |
| packages/video-player/javascript/modules/playlist/playlist-menu-item.ts | Clones playlist items before applying default poster transformation; caches prepared thumbnail. |
| packages/video-player/javascript/modules/analytics/wire-format-v1.ts | Defines v1 positional wire schema + context key mapping + encoder/decoder utilities. |
| packages/video-player/javascript/modules/analytics/video-scale-percentage.ts | Computes up/down-scale percentages from decoded vs displayed video size. |
| packages/video-player/javascript/modules/analytics/types.ts | Adds analytics event/context types aligned with ingest schema expectations. |
| packages/video-player/javascript/modules/analytics/transport.ts | Implements gzip→base64url GET transport with conditional keepalive. |
| packages/video-player/javascript/modules/analytics/player-adapter.ts | Adapts Video.js runtime events into normalized analytics signals. |
| packages/video-player/javascript/modules/analytics/id-factory.ts | Generates/persists session/player/playback/event identifiers. |
| packages/video-player/javascript/modules/analytics/event-row-encoder.ts | Encodes internal events into canonical/slim shapes for wire encoding. |
| packages/video-player/javascript/modules/analytics/constants.ts | Adds analytics defaults (ingest URL, batching knobs, thresholds). |
| packages/video-player/javascript/modules/analytics/batch-queue.ts | Buffers events and flushes on interval/size/lifecycle triggers. |
| packages/video-player/javascript/modules/analytics/analytics-tracker.ts | Orchestrates state machine + adapter + batching + context capture; hooks into plugin lifecycle. |
| packages/video-player/javascript/modules/analytics/analytics-state-machine.ts | Enforces valid analytics event sequencing and computes timings. |
| packages/video-player/javascript/interfaces/Player.ts | Extends public options with analytics config + error mapping types. |
| packages/video-player/javascript/index.ts | Instantiates the analytics tracker when analytics.enabled is true. |
| packages/video-player/astro/IKVideoPlayer.astro | Adds imperative mapError wiring support for Astro (functions not serializable). |
| examples/vue/src/App.vue | Demonstrates enabling analytics in Vue example config. |
| examples/react/src/App.tsx | Demonstrates enabling analytics in React example config. |
| examples/javascript/vite.config.ts | Adds a second “try-it-yourself” page entry. |
| examples/javascript/src/try-it-yourself.ts | Enables analytics via feature toggle in the JS example configurator. |
| examples/javascript/pages/try-it-yourself-2.html | Adds an internal test page with analytics option in the UI. |
| examples/astro/src/pages/index.astro | Adds an Astro example showing imperative mapError usage. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+415
to
+418
| case 'dispose': | ||
| stateMachine.dispatch({ type: 'dispose' }, captureContext); | ||
| batchQueue.flush('dispose'); | ||
| break; |
Comment on lines
+144
to
+149
| ingestUrl: config.ingestUrl, | ||
| flushIntervalMs: config.flushIntervalMs, | ||
| maxBatchSize: config.maxBatchSize, | ||
| debug: config.debug, | ||
| }); | ||
|
|
Comment on lines
+423
to
+432
| // Flush when page goes hidden (e.g. tab switch, navigation away). | ||
| if (typeof document !== 'undefined') { | ||
| const onVisibilityChange = () => { | ||
| if (document.visibilityState === 'hidden') { | ||
| batchQueue.flush('visibility_hidden'); | ||
| } | ||
| }; | ||
| document.addEventListener('visibilitychange', onVisibilityChange); | ||
| cleanup.register(() => document.removeEventListener('visibilitychange', onVisibilityChange)); | ||
| } |
Comment on lines
+1
to
+5
| /** | ||
| * Batches analytics events and flushes to ingest server. | ||
| * v1 transport: every flush is a `GET ingestUrl?d=<base64url(gzip(json))>` with `keepalive: true`. | ||
| * Size-based flush trigger guarantees URL stays under ANALYTICS_URL_SAFE_LIMIT_BYTES. | ||
| */ |
Comment on lines
+67
to
+70
| // Size-based trigger: keep URL safely under the limit. | ||
| if (projectedBatchJsonLength() >= ANALYTICS_RAW_JSON_FLUSH_THRESHOLD) { | ||
| doFlush('size_limit'); | ||
| } |
Comment on lines
+1
to
+2
| /** Analytics ingest endpoint. */ | ||
| export const ANALYTICS_INGEST_URL = 'https://stage-ikedge.imagekit.io/b'; |
Comment on lines
+55
to
+58
| if (item.prepared.playlistThumbnail) { | ||
| return item.prepared.playlistThumbnail; | ||
| } | ||
| if (!item.poster?.transformation) { | ||
| if (!item.poster) { | ||
| item.poster = {}; | ||
| } | ||
| item.poster.transformation = [DEFAULT_TRANSFORMATION] | ||
|
|
||
|
|
… user activity tracking
… and update analytics interfaces
…tics state machine
…sions, and mapError functionality
Comment on lines
+239
to
+247
| // Mint a new playback_id for the rotated view; tracker is the owner of playback ids. | ||
| const newPlaybackId = createPlaybackId(); | ||
| currentPlaybackId = newPlaybackId; | ||
| stateMachine.dispatch({ | ||
| type: 'session_rotated', | ||
| newPlaybackId, | ||
| previousSessionId, | ||
| videoSourceUrl: previousVideoSourceUrl ?? undefined, | ||
| }); |
Comment on lines
+23
to
+26
| const PLUGIN_NAME = 'imagekit-video-player'; | ||
| const PLUGIN_VERSION = '1.0.0-beta.1'; | ||
| const PLAYER_SOFTWARE = 'video.js'; | ||
| const PLAYER_SOFTWARE_VERSION = '8.20.0'; |
Comment on lines
+245
to
+246
| type MapErrorFn = (error: { code: string; message?: string; context?: string }) => | ||
| { code?: string; message?: string; context?: string } | null | undefined; |
Comment on lines
+51
to
+56
| function doFlush(reason: FlushReason) { | ||
| if (events.length === 0 || !lastContext) return; | ||
| const batch = events.splice(0, events.length); | ||
| const slim = batch.map(toSlimEvent); | ||
| const req = buildIngestRequestV1(lastContext, slim, reason ?? ''); | ||
| if (debug) { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.