Skip to content

feat(analytics): add video analytics pipeline with ingest server, event tracking, and ClickHouse schema#3

Open
aman051197 wants to merge 21 commits into
mainfrom
video_analytics
Open

feat(analytics): add video analytics pipeline with ingest server, event tracking, and ClickHouse schema#3
aman051197 wants to merge 21 commits into
mainfrom
video_analytics

Conversation

@aman051197

Copy link
Copy Markdown
Collaborator

No description provided.

… player adapter to prevent unintended pause events
aman-imagekit and others added 3 commits May 28, 2026 08:56
…n_fix

Enhance analytics tracking with custom dimensions and transport improvements
@aman051197 aman051197 changed the base branch from dev to main June 2, 2026 03:01
@aman051197 aman051197 requested a review from Copilot June 2, 2026 03:19

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 analytics options to the public IKPlayerOptions.
  • 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]


Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 5 comments.

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 thread packages/video-player/javascript/modules/analytics/constants.ts
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) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants