Skip to content

Commit

Permalink
Migrate to Media Tracking plugin for HTML5 Plugin (#1344)
Browse files Browse the repository at this point in the history
  • Loading branch information
greg-el committed Oct 8, 2024
1 parent baec2a9 commit 6574aa3
Show file tree
Hide file tree
Showing 29 changed files with 1,127 additions and 1,399 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@snowplow/browser-plugin-media-tracking",
"comment": "Migrate HTML Media Tracking to Snowplow Media Plugin",
"type": "none"
}
],
"packageName": "@snowplow/browser-plugin-media-tracking"
}
9 changes: 9 additions & 0 deletions common/config/rush/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion common/config/rush/repo-state.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush.
{
"pnpmShrinkwrapHash": "c364f96ddb4f2ccb56f10dceb499162dffc440f8",
"pnpmShrinkwrapHash": "64adeaeaaaae09f264464fa44834bfe036401311",
"preferredVersionsHash": "bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f"
}
1 change: 1 addition & 0 deletions plugins/browser-plugin-media-tracking/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ module.exports = {
preset: 'ts-jest',
reporters: ['jest-standard-reporter'],
testEnvironment: 'jest-environment-jsdom-global',
setupFilesAfterEnv: ['../../setupTestGlobals.ts'],
};
5 changes: 4 additions & 1 deletion plugins/browser-plugin-media-tracking/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,19 @@
"test": "jest"
},
"dependencies": {
"@snowplow/browser-plugin-media": "workspace:*",
"@snowplow/browser-tracker-core": "workspace:*",
"@snowplow/tracker-core": "workspace:*",
"tslib": "^2.3.1"
"tslib": "^2.3.1",
"uuid": "^8.3.2"
},
"devDependencies": {
"@ampproject/rollup-plugin-closure-compiler": "~0.27.0",
"@rollup/plugin-commonjs": "~21.0.2",
"@rollup/plugin-node-resolve": "~13.1.3",
"@types/jest": "~27.4.1",
"@types/jsdom": "~16.2.14",
"@types/uuid": "^8.3.2",
"@typescript-eslint/eslint-plugin": "~5.15.0",
"@typescript-eslint/parser": "~5.15.0",
"eslint": "~8.11.0",
Expand Down
82 changes: 82 additions & 0 deletions plugins/browser-plugin-media-tracking/src/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { Logger } from '@snowplow/tracker-core';
import { BrowserPlugin, BrowserTracker } from '@snowplow/browser-tracker-core';
import { waitForElement } from './findElem';
import { Config, isElementConfig, isStringConfig } from './config';
import { setUpListeners } from './player';
import { setConfigDefaults } from './helperFunctions';

// These imports are used for documentation purposes only.
// Typescript complains that they are unused.
// @ts-ignore: TS6133
import { DynamicContext } from '@snowplow/tracker-core';
// @ts-ignore: TS6133
import { HTML5MediaEventTypes } from './config';
// @ts-ignore: TS6133
import { FilterOutRepeatedEvents } from '@snowplow/browser-plugin-media/src/types';

import { endMediaTracking } from '@snowplow/browser-plugin-media';

let LOG: Logger;
const _trackers: Record<string, BrowserTracker> = {};

export function MediaTrackingPlugin(): BrowserPlugin {
return {
activateBrowserPlugin: (tracker: BrowserTracker) => {
_trackers[tracker.id] = tracker;
},
logger: (logger) => {
LOG = logger;
},
};
}

/**
* Enables media tracking on an HTML `<video>` or `<audio>` element.
*
* @param {Config} config - Configuration options for media tracking.
*
* **Required:**
* - `config.id` (`string`): The session ID. Must be unique for each media element. Used to identify the media session and end tracking.
* - `config.video` (string | HTMLMediaElement): The ID of the media element or the element itself.
*
* **Optional:**
* - `config.label` (`string`): A human-readable label for the media element.
* - `config.captureEvents` {@link HTML5MediaEventTypes}: A list of media events to track. All events are tracked by default.
* - `config.boundaries` (`number[]`): Percentage thresholds (0-100) at which to trigger progress events. Disabled by default.
* - `config.context` {@link DynamicContext}: Contexts to attach to each tracking event.
*
* **Ping Configuration (Optional):**
* - `config.pings.pingInterval` (`number`): The interval (in seconds) for sending ping events. Default is 30(s).
* - `config.pings.maxPausedPings` (`number`): The maximum number of ping events sent while playback is paused. Default is 1.
*
* **Other Options (Optional):**
* - `config.updatePageActivityWhilePlaying` (`boolean`): Whether to update page activity while media is playing. Enabled by default.
* - `config.filterOutRepeatedEvents` {@link FilterOutRepeatedEvents}: Whether to suppress consecutive identical events. Default is false.
*/
export function startHtml5MediaTracking(config: Config) {
if (!config.video) {
LOG.error(
"Missing 'video' property in the enableMediaTracking configuration. ",
"Ensure the 'config.video' property is correctly set. Current config: ",
config
);
return;
}

config = setConfigDefaults(config);

if (isStringConfig(config)) {
waitForElement(config, setUpListeners);
} else if (isElementConfig(config)) {
setUpListeners(config);
}
}

/**
* Ends media tracking with the given ID if previously started. Clears local state for the media tracking and sends any events waiting to be sent.
*
* @param {string} id - The session ID.
*/
export function endHtml5MediaTracking(id: string) {
endMediaTracking({ id });
}
94 changes: 0 additions & 94 deletions plugins/browser-plugin-media-tracking/src/buildMediaEvent.ts

This file was deleted.

42 changes: 42 additions & 0 deletions plugins/browser-plugin-media-tracking/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { MediaEventType } from '@snowplow/browser-plugin-media';
import { CommonMediaEventProperties, MediaTrackingConfiguration } from '@snowplow/browser-plugin-media/src/types';

export type HTML5MediaEventTypes = Extract<
MediaEventType,
| MediaEventType.Ready
| MediaEventType.Play
| MediaEventType.Pause
| MediaEventType.End
| MediaEventType.SeekEnd
| MediaEventType.PlaybackRateChange
| MediaEventType.VolumeChange
| MediaEventType.FullscreenChange
| MediaEventType.PictureInPictureChange
| MediaEventType.BufferStart
| MediaEventType.BufferEnd
| MediaEventType.Error
| MediaEventType.Ping
| MediaEventType.PercentProgress
>;

export type Config = {
video: string | HTMLMediaElement;
label?: string;
} & CommonMediaEventProperties &
Omit<MediaTrackingConfiguration, 'player'>;

export interface StringConfig extends Config {
video: string;
}

export function isStringConfig(config: Config): config is StringConfig {
return typeof config.video === 'string';
}

export interface ElementConfig extends Config {
video: HTMLMediaElement;
}

export function isElementConfig(config: Config): config is ElementConfig {
return config.video instanceof HTMLMediaElement;
}
24 changes: 5 additions & 19 deletions plugins/browser-plugin-media-tracking/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { TextTrackEvent } from './mediaEvents';
import { SearchError } from './types';

export enum SEARCH_ERROR {
NOT_FOUND = 'Media element not found',
MULTIPLE_ELEMENTS = 'More than one media element in the provided node',
PLYR_CURRENTSRC = 'Plyr currentSrc not updated',
}
export const READY_STATE: Record<number, string> = {
0: 'HAVE_NOTHING',
1: 'HAVE_METADATA',
Expand All @@ -15,19 +17,3 @@ export const NETWORK_STATE: Record<number, string> = {
2: 'NETWORK_LOADING',
3: 'NETWORK_NO_SOURCE',
};

export const TAG: Record<string, string> = {
VIDEO: 'VIDEO',
AUDIO: 'AUDIO',
};

export const SEARCH_ERROR: SearchError = {
NOT_FOUND: 'Media element not found',
MULTIPLE_ELEMENTS: 'More than one media element in the provided node',
PLYR_CURRENTSRC: 'Plyr currentSrc not updated',
};

export const eventNames: Record<string, string> = {
[TextTrackEvent.CHANGE]: 'texttrackchange',
};
Object.keys(eventNames).forEach((k) => (eventNames[eventNames[k]] = k));
Loading

0 comments on commit 6574aa3

Please sign in to comment.