From 7ea36be8b3a00675e96d76db551c9dbe3accde41 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 8 Jun 2024 20:00:50 +0200 Subject: [PATCH 01/26] open existing test page in serve script --- comscore/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/comscore/package.json b/comscore/package.json index 2f1ab53..6658fbb 100644 --- a/comscore/package.json +++ b/comscore/package.json @@ -20,7 +20,7 @@ "bundle": "rollup -c rollup.config.mjs", "watch": "npm run bundle -- --watch", "build": "npm run clean && npm run bundle", - "serve": "http-server ./.. -o /comscore/test/pages/main.html", + "serve": "http-server ./.. -o /comscore/test/pages/main_umd.html", "test": "echo \"No tests yet\"" }, "repository": { From 8dd5dfe0b18bcdd17c8cf3d6d6b40123edffc737 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 8 Jun 2024 22:14:48 +0200 Subject: [PATCH 02/26] provide ad duration in milliseconds --- .../ComscoreStreamingAnalyticsTHEOIntegration.ts | 3 ++- comscore/src/integration/Utils.ts | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 comscore/src/integration/Utils.ts diff --git a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts index 352905d..f140a07 100644 --- a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts +++ b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts @@ -18,6 +18,7 @@ import { import { ComscoreConfiguration } from '../api/ComscoreConfiguration'; import { ComscoreMetadata } from '../api/ComscoreMetadata'; import { buildContentMetadata } from './ComscoreContentMetadata'; +import { toMilliSeconds } from './Utils'; const LOG_STATE_CHANGES = true; const LOG_THEOPLAYER_EVENTS = true; @@ -439,7 +440,7 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { ad.adBreak.integration ?? '' ); this.lastAdId = adIdProcessor ? adIdProcessor(ad) : ad.id; - this.lastAdDuration = ad.duration; + this.lastAdDuration = toMilliSeconds(ad.duration); if (!this.lastAdDuration && this.configuration.debug) { console.log('[COMSCORE] AD_BEGIN event with an ad duration of 0 found. Please check the ad configuration'); } diff --git a/comscore/src/integration/Utils.ts b/comscore/src/integration/Utils.ts new file mode 100644 index 0000000..3827b90 --- /dev/null +++ b/comscore/src/integration/Utils.ts @@ -0,0 +1,6 @@ +export const toMilliSeconds = (seconds: number | undefined) => { + if (seconds === undefined) { + return undefined + } + return seconds * 1000 +} \ No newline at end of file From c4ddb31d2e6bef4205c305eadeef61e3501caea7 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 8 Jun 2024 22:17:29 +0200 Subject: [PATCH 03/26] use rounded amount of milliseconds --- comscore/src/integration/Utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/comscore/src/integration/Utils.ts b/comscore/src/integration/Utils.ts index 3827b90..a3d8767 100644 --- a/comscore/src/integration/Utils.ts +++ b/comscore/src/integration/Utils.ts @@ -2,5 +2,5 @@ export const toMilliSeconds = (seconds: number | undefined) => { if (seconds === undefined) { return undefined } - return seconds * 1000 + return Math.round(seconds * 1000) } \ No newline at end of file From 9d5308465ae260f9741b0ad44069f00f9c8289a9 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 8 Jun 2024 22:40:40 +0200 Subject: [PATCH 04/26] catch undefined ad durations before conversion to ms --- .../integration/ComscoreStreamingAnalyticsTHEOIntegration.ts | 2 +- comscore/src/integration/Utils.ts | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts index f140a07..ef1aa90 100644 --- a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts +++ b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts @@ -440,7 +440,7 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { ad.adBreak.integration ?? '' ); this.lastAdId = adIdProcessor ? adIdProcessor(ad) : ad.id; - this.lastAdDuration = toMilliSeconds(ad.duration); + this.lastAdDuration = toMilliSeconds(ad.duration ?? 0); if (!this.lastAdDuration && this.configuration.debug) { console.log('[COMSCORE] AD_BEGIN event with an ad duration of 0 found. Please check the ad configuration'); } diff --git a/comscore/src/integration/Utils.ts b/comscore/src/integration/Utils.ts index a3d8767..0f05945 100644 --- a/comscore/src/integration/Utils.ts +++ b/comscore/src/integration/Utils.ts @@ -1,6 +1,3 @@ -export const toMilliSeconds = (seconds: number | undefined) => { - if (seconds === undefined) { - return undefined - } +export const toMilliSeconds = (seconds: number) => { return Math.round(seconds * 1000) } \ No newline at end of file From 75a512d3493c168e313050d26ae49d382c8b7ea4 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 8 Jun 2024 22:41:06 +0200 Subject: [PATCH 05/26] use rounded amount of milliseconds when reporting new playback position --- .../integration/ComscoreStreamingAnalyticsTHEOIntegration.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts index ef1aa90..0030bec 100644 --- a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts +++ b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts @@ -415,9 +415,10 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { ); } else { if (this.configuration.debug) console.log(`[COMSCORE] seeked in a VOD stream`); - this.streamingAnalytics.startFromPosition(currentTime * 1000); + const currentTimeInMilliSeconds = toMilliSeconds(currentTime) + this.streamingAnalytics.startFromPosition(currentTimeInMilliSeconds); if (this.configuration.debug && LOG_STREAMINGANALYTICS) - console.log(`[COMSCORE - StreamingAnalytics] startFromPosition ${currentTime * 1000}`); + console.log(`[COMSCORE - StreamingAnalytics] startFromPosition ${currentTimeInMilliSeconds}`); } }; From 234d4181f18a22e5cc44e32e534330f760e74569 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sun, 9 Jun 2024 12:47:00 +0200 Subject: [PATCH 06/26] store the built ContentMetadata object in contentMetadata property --- .../integration/ComscoreStreamingAnalyticsTHEOIntegration.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts index 0030bec..0eaedfd 100644 --- a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts +++ b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts @@ -151,7 +151,9 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { adMetadata.setUniqueId(adId); adMetadata.setLength(adDuration); - if (!this.contentMetadata) buildContentMetadata(this.metadata); + if (!this.contentMetadata) { + this.contentMetadata = buildContentMetadata(this.metadata); + } adMetadata.setRelatedContentMetadata(this.contentMetadata); if (this.configuration.debug && LOG_STREAMINGANALYTICS) { console.log(`[COMSCORE - StreamingAnalytics] setMetadata (advertisement)`, adMetadata.getMetadataLabels()); From 20ebeb1c1ad36c364afe1d025d5046b4f771e432 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sun, 9 Jun 2024 22:56:23 +0200 Subject: [PATCH 07/26] call notifyEnd and set new ad metadata after each ad --- .../ComscoreStreamingAnalyticsTHEOIntegration.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts index 0eaedfd..fe06651 100644 --- a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts +++ b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts @@ -99,6 +99,7 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { if (this.player.ads) { this.player.ads.addEventListener('adbegin', this.onAdBegin); + this.player.ads.addEventListener('adend', this.onAdEnd); this.player.ads.addEventListener('adbreakend', this.onAdBreakEnd); } } @@ -118,6 +119,7 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { if (this.player.ads) { this.player.ads.removeEventListener('adbegin', this.onAdBegin); + this.player.ads.removeEventListener('adend', this.onAdEnd); this.player.ads.removeEventListener('adbreakend', this.onAdBreakEnd); } } @@ -458,6 +460,12 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { } }; + private onAdEnd = (event: AdEvent<'adend'>) => { + if (this.configuration.debug && LOG_THEOPLAYER_EVENTS) + console.log(`[COMSCORE - THEOplayer EVENTS] ${event.type} event`); + this.transitionToStopped(); + } + private onAdBreakEnd = (event: AdBreakEvent<'adbreakend'>) => { if (this.configuration.debug && LOG_THEOPLAYER_EVENTS) console.log(`[COMSCORE - THEOplayer EVENTS] ${event.type} event`); From 9da96d0a1d68075ebe6b0f564848ebd7a429e68c Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Thu, 13 Jun 2024 09:20:06 +0200 Subject: [PATCH 08/26] introduce dvr window related properties --- .../ComscoreStreamingAnalyticsTHEOIntegration.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts index fe06651..cd7dcfc 100644 --- a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts +++ b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts @@ -57,6 +57,10 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { // Copy of main content's ContentMetadata private contentMetadata: ns_.analytics.StreamingAnalytics.ContentMetadata | null = null; + // Main content related fields for use outside of event handlers + private dvrWindowLengthMs: number | undefined = undefined + private dvrWindowOffsetMs: number | undefined = undefined + // Advertisement related fields for use outside of ad event handlers private inAd: boolean = false; private lastAdId: string | undefined = undefined; @@ -288,6 +292,8 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { console.log(`[COMSCORE - THEOplayer EVENTS] ${event.type} event`); this.state = ComscoreState.INITIALIZED; this.contentMetadata = null; + this.dvrWindowLengthMs = undefined; + this.dvrWindowOffsetMs = undefined; this.streamingAnalytics.createPlaybackSession(); if (this.configuration.debug && LOG_STREAMINGANALYTICS) console.log(`[COMSCORE - StreamingAnalytics] createPlaybackSession`); From bd490c02003d2f4712aa6d444cde2a6b2f124518 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Thu, 13 Jun 2024 09:21:01 +0200 Subject: [PATCH 09/26] store dvr window offset in ms --- .../ComscoreStreamingAnalyticsTHEOIntegration.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts index cd7dcfc..a179406 100644 --- a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts +++ b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts @@ -418,11 +418,14 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { } const dvrWindowEnd = seekable.end(seekable.length - 1); const dvrWindowOffsetInSeconds = dvrWindowEnd - currentTime; - this.streamingAnalytics.startFromDvrWindowOffset(dvrWindowOffsetInSeconds * 1000); - if (this.configuration.debug && LOG_STREAMINGANALYTICS) - console.log( - `[COMSCORE - StreamingAnalytics] startFromDvrWindowOffset ${dvrWindowOffsetInSeconds * 1000}` - ); + this.dvrWindowOffsetMs = toMilliSeconds(dvrWindowOffsetInSeconds) + if (this.state === ComscoreState.VIDEO || this.state === ComscoreState.VIDEO_PAUSED) { + this.streamingAnalytics.startFromDvrWindowOffset(this.dvrWindowOffsetMs); + if (this.configuration.debug && LOG_STREAMINGANALYTICS) + console.log( + `[COMSCORE - StreamingAnalytics] startFromDvrWindowOffset ${this.dvrWindowOffsetMs}` + ); + } } else { if (this.configuration.debug) console.log(`[COMSCORE] seeked in a VOD stream`); const currentTimeInMilliSeconds = toMilliSeconds(currentTime) From c2430564df44e0399df1ad570bc27472ec12de76 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Thu, 13 Jun 2024 09:21:30 +0200 Subject: [PATCH 10/26] store dvr window length in ms --- .../ComscoreStreamingAnalyticsTHEOIntegration.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts index a179406..49ca142 100644 --- a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts +++ b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts @@ -376,11 +376,8 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { const dvrWindowStart = seekable.start(0); const dvrWindowLengthInSeconds = dvrWindowEnd - dvrWindowStart; if (dvrWindowLengthInSeconds) { - this.streamingAnalytics.setDvrWindowLength(dvrWindowLengthInSeconds * 1000); - if (this.configuration.debug && LOG_STREAMINGANALYTICS) - console.log( - `[COMSCORE - StreamingAnalytics] setDvrWindowLength ${dvrWindowLengthInSeconds * 1000}` - ); + this.dvrWindowLengthMs = toMilliSeconds(dvrWindowLengthInSeconds) + if (this.state === ComscoreState.VIDEO || this.state === ComscoreState.VIDEO_PAUSED) this.streamingAnalytics.setDvrWindowLength(this.dvrWindowLengthMs) } else if (this.configuration.debug) console.log(`[COMSCORE] DVR window length was not > 0`); } } catch (error) { From eab424dc346d5fe5118248eeb3570d6b71b9b425 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Thu, 13 Jun 2024 09:22:11 +0200 Subject: [PATCH 11/26] report dvr window properties to comscore after setting main content metadata --- .../ComscoreStreamingAnalyticsTHEOIntegration.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts index 49ca142..f2486f9 100644 --- a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts +++ b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts @@ -177,6 +177,12 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { console.log(`[COMSCORE - STATE] State change ${this.state} -> VIDEO`); this.state = ComscoreState.VIDEO; this.setContentMetadata(); + if (this.dvrWindowLengthMs) { + this.streamingAnalytics.setDvrWindowLength(this.dvrWindowLengthMs) + if (this.configuration.debug && LOG_STREAMINGANALYTICS) console.log(`[COMSCORE - StreamingAnalytics] setDvrWindowLength ${this.dvrWindowLengthMs}`); + this.streamingAnalytics.startFromDvrWindowOffset(this.dvrWindowOffsetMs ?? 0) + if (this.configuration.debug && LOG_STREAMINGANALYTICS) console.log(`[COMSCORE - StreamingAnalytics] startFromDvrWindowOffset ${this.dvrWindowOffsetMs}`); + } break; case ComscoreState.ADVERTISEMENT: case ComscoreState.ADVERTISEMENT_PAUSED: @@ -186,6 +192,12 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { console.log(`[COMSCORE - STATE] State change ${this.state} -> VIDEO`); this.state = ComscoreState.VIDEO; this.setContentMetadata(); + if (this.dvrWindowLengthMs) { + this.streamingAnalytics.setDvrWindowLength(this.dvrWindowLengthMs) + if (this.configuration.debug && LOG_STREAMINGANALYTICS) console.log(`[COMSCORE - StreamingAnalytics] setDvrWindowLength ${this.dvrWindowLengthMs}`); + this.streamingAnalytics.startFromDvrWindowOffset(this.dvrWindowOffsetMs ?? 0) + if (this.configuration.debug && LOG_STREAMINGANALYTICS) console.log(`[COMSCORE - StreamingAnalytics] startFromDvrWindowOffset ${this.dvrWindowOffsetMs}`); + } break; case ComscoreState.VIDEO_PAUSED: if (this.configuration.debug && LOG_STATE_CHANGES) From e67c03253bf0427b8dbf07e684dbb1745428d2e9 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Fri, 13 Sep 2024 16:55:39 +0200 Subject: [PATCH 12/26] add changesets --- .changeset/blue-gorillas-lie.md | 5 +++++ .changeset/chilled-lamps-happen.md | 5 +++++ .changeset/kind-pugs-grin.md | 5 +++++ 3 files changed, 15 insertions(+) create mode 100644 .changeset/blue-gorillas-lie.md create mode 100644 .changeset/chilled-lamps-happen.md create mode 100644 .changeset/kind-pugs-grin.md diff --git a/.changeset/blue-gorillas-lie.md b/.changeset/blue-gorillas-lie.md new file mode 100644 index 0000000..1f24a6b --- /dev/null +++ b/.changeset/blue-gorillas-lie.md @@ -0,0 +1,5 @@ +--- +"@theoplayer/comscore-connector-web": patch +--- + +Fixed an issue where DVR window length and offsets were incorrectly reported. diff --git a/.changeset/chilled-lamps-happen.md b/.changeset/chilled-lamps-happen.md new file mode 100644 index 0000000..3e245cf --- /dev/null +++ b/.changeset/chilled-lamps-happen.md @@ -0,0 +1,5 @@ +--- +"@theoplayer/comscore-connector-web": patch +--- + +Fixed an issue where playhead positions or content/ad durations were not reported in (rounded) milliseconds. diff --git a/.changeset/kind-pugs-grin.md b/.changeset/kind-pugs-grin.md new file mode 100644 index 0000000..e36f568 --- /dev/null +++ b/.changeset/kind-pugs-grin.md @@ -0,0 +1,5 @@ +--- +"@theoplayer/comscore-connector-web": patch +--- + +Fixed an issue where only one ad in an adbreak would be reported. From e40bdfa3ca39250592fbd040d7c25b243227e620 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Fri, 13 Sep 2024 16:57:47 +0200 Subject: [PATCH 13/26] Accept ComscoreConfiguration property to set the platform api --- comscore/src/api/ComscoreConfiguration.ts | 1 + comscore/src/api/ComscoreConnector.ts | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/comscore/src/api/ComscoreConfiguration.ts b/comscore/src/api/ComscoreConfiguration.ts index 9d06e5a..dd722cb 100644 --- a/comscore/src/api/ComscoreConfiguration.ts +++ b/comscore/src/api/ComscoreConfiguration.ts @@ -24,6 +24,7 @@ export interface ComscoreConfiguration { */ usagePropertiesAutoUpdateMode?: ComscoreUsagePropertiesAutoUpdateMode; skeleton?: any; + platformApi?: ns_.analytics.PlatformAPIs; adIdProcessor?: (ad: Ad) => string; debug?: boolean; } diff --git a/comscore/src/api/ComscoreConnector.ts b/comscore/src/api/ComscoreConnector.ts index a79338f..8e6a6b0 100644 --- a/comscore/src/api/ComscoreConnector.ts +++ b/comscore/src/api/ComscoreConnector.ts @@ -28,7 +28,10 @@ export class ComscoreConnector { // Set platform API if (this.configuration.skeleton) { this.analytics.PlatformApi.setPlatformAPI(this.analytics.PlatformAPIs.Skeleton, this.configuration.skeleton) - } else { + } else if (this.configuration.platformApi){ + this.analytics.PlatformApi.setPlatformAPI(this.configuration.platformApi) + if (this.configuration.debug) console.log(`[COMSCORE] Set the Platform API to ${this.configuration.platformApi}`) + } else { this.analytics.PlatformApi.setPlatformAPI(this.analytics.PlatformAPIs.html5) } From 173bfc050126099e65a16b66b5c44f38dfe61ac8 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Fri, 13 Sep 2024 16:58:13 +0200 Subject: [PATCH 14/26] add platform api example --- comscore/test/pages/main_esm.html | 1 + 1 file changed, 1 insertion(+) diff --git a/comscore/test/pages/main_esm.html b/comscore/test/pages/main_esm.html index 6f48152..3775d96 100644 --- a/comscore/test/pages/main_esm.html +++ b/comscore/test/pages/main_esm.html @@ -58,6 +58,7 @@ applicationName: 'Test App', userConsent: "1", adIdProcessor: (ad) => ad.id, + platformApi: ns_.analytics.PlatformAPIs.WebBrowser, debug: true }; From bfc67015497c1f402ea363162e2d7957148dc02d Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Fri, 13 Sep 2024 17:01:19 +0200 Subject: [PATCH 15/26] add changeset --- .changeset/wise-vans-begin.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/wise-vans-begin.md diff --git a/.changeset/wise-vans-begin.md b/.changeset/wise-vans-begin.md new file mode 100644 index 0000000..0c2f4f2 --- /dev/null +++ b/.changeset/wise-vans-begin.md @@ -0,0 +1,5 @@ +--- +"@theoplayer/comscore-connector-web": minor +--- + +Add the option to inform the ComScore library of the environment it is running in through the `setPlatformAPI`. From 6180f4b91648878661b5e13fdc16a0f65ef9e031 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Fri, 13 Sep 2024 17:17:01 +0200 Subject: [PATCH 16/26] Extend README --- comscore/README.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/comscore/README.md b/comscore/README.md index 773e446..c67ea9c 100644 --- a/comscore/README.md +++ b/comscore/README.md @@ -27,6 +27,7 @@ const comscoreConfig = { publisherId: '', applicationName: 'Test App', userConsent: '1', + platformApi: ns_.analytics.PlatformAPIs.WebBrowser, debug: true }; @@ -47,6 +48,43 @@ const comscoreMetadata = { const comscoreConnector = new ComscoreConnector(player, comscoreConfig, comscoreMetadata); ``` +### Optional ComscoreConfiguration properties + +#### `usagePropertiesAutoUpdateMode` + +When omitted this wil default to foregroundOnly. + +#### `skeleton` + +Pass an interface object with target platform specific implementations for the necessary Platform APIs. E.g. + +```js +analytics.PlatformApi.setPlatformApi(analytics.PlatformApi.PlatformApis.Skeleton, { + onDataFetch: function (onSuccessCallback, onErrorCallback) { + // Execute a function with platform-specific code to retrieve up-to-date information. + runPlatformSpecificCodeToRetrieveValues(onSuccessCallback, onErrorCallback); + } + // + // Other overridden PlatformAPI methods, as needed. +}); +``` + +For more information, please consult the [Skeleton PlatformAPI Implementation Guide](https://mymetrix-support.comscore.com/hc/en-us/article_attachments/19635711827867) + +Note that if the skeleton property is defined, the connector will always use `setPlatformAPI(ns_.analytics.PlatformAPIs.Skeleton)`. + +#### `platformApi` + +Pass a valid value from `ns_.analytics.PlatformAPIs`. When omitted, the connector will report `setPlatformAPI(ns_.analytics.PlatformAPIs.html5)`. + +#### `adIdProcessor` + +Pass a function with the following signature if you require custom ad id handling: `(ad: Ad) => string`. When omitted, the connector will use `(ad) => ad.id`. Consult THEOplayer's types for more info about the `Ad` interface. + +#### `debug` + +A flag to enable verbose logging. + ### Passing metadata dynamically The connector allows updating the current asset's metadata at any time. Do it when setting a new source to the player. From c4c6913d7015e0237275d491c88e0b2ffef8bed9 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Fri, 13 Sep 2024 17:45:36 +0200 Subject: [PATCH 17/26] Fix typedoc warning --- comscore/src/api/ComscoreConfiguration.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/comscore/src/api/ComscoreConfiguration.ts b/comscore/src/api/ComscoreConfiguration.ts index dd722cb..4a8e084 100644 --- a/comscore/src/api/ComscoreConfiguration.ts +++ b/comscore/src/api/ComscoreConfiguration.ts @@ -24,7 +24,10 @@ export interface ComscoreConfiguration { */ usagePropertiesAutoUpdateMode?: ComscoreUsagePropertiesAutoUpdateMode; skeleton?: any; - platformApi?: ns_.analytics.PlatformAPIs; + /** + * Defaults to ns_.analytics.PlatformAPIs.html5 if no skeleton is provided or ns_.analytics.PlatformAPIs.Skeleton if a skeleton is provided. + */ + platformApi?: number; adIdProcessor?: (ad: Ad) => string; debug?: boolean; } From d5703f7fcc2ce32d9f8f06bbea3bbe85e638f004 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 14 Sep 2024 22:28:02 +0200 Subject: [PATCH 18/26] use mapped platform api type --- comscore/src/api/ComscoreConfiguration.ts | 20 ++++++++++- comscore/src/api/ComscoreConnector.ts | 43 +++++++++++++++++++++-- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/comscore/src/api/ComscoreConfiguration.ts b/comscore/src/api/ComscoreConfiguration.ts index 4a8e084..5d0b0b1 100644 --- a/comscore/src/api/ComscoreConfiguration.ts +++ b/comscore/src/api/ComscoreConfiguration.ts @@ -12,6 +12,24 @@ export enum ComscoreUsagePropertiesAutoUpdateMode { disabled = "disabled" } +export enum ComscorePlatformAPIs { + SmartTV = 0, + Netcast = 1, + Cordova = 2, + Trilithium = 3, + AppleTV = 4, + Chromecast = 5, + Xbox = 6, + webOS = 7, + tvOS = 8, + nodejs = 9, + html5 = 10, + JSMAF = 11, + Skeleton = 12, + WebBrowser = 13, + SamsungTizenTV = 14 +} + export interface ComscoreConfiguration { /** * Also known as the c2 value @@ -27,7 +45,7 @@ export interface ComscoreConfiguration { /** * Defaults to ns_.analytics.PlatformAPIs.html5 if no skeleton is provided or ns_.analytics.PlatformAPIs.Skeleton if a skeleton is provided. */ - platformApi?: number; + platformApi?: ComscorePlatformAPIs; adIdProcessor?: (ad: Ad) => string; debug?: boolean; } diff --git a/comscore/src/api/ComscoreConnector.ts b/comscore/src/api/ComscoreConnector.ts index 8e6a6b0..58480f0 100644 --- a/comscore/src/api/ComscoreConnector.ts +++ b/comscore/src/api/ComscoreConnector.ts @@ -1,5 +1,5 @@ import { ChromelessPlayer } from 'theoplayer'; -import type { ComscoreConfiguration, ComscoreUserConsent } from './ComscoreConfiguration'; +import { ComscoreConfiguration, ComscorePlatformAPIs, ComscoreUserConsent } from './ComscoreConfiguration'; import type { ComscoreMetadata } from './ComscoreMetadata'; import { ComscoreStreamingAnalyticsTHEOIntegration } from '../integration/ComscoreStreamingAnalyticsTHEOIntegration'; @@ -29,7 +29,7 @@ export class ComscoreConnector { if (this.configuration.skeleton) { this.analytics.PlatformApi.setPlatformAPI(this.analytics.PlatformAPIs.Skeleton, this.configuration.skeleton) } else if (this.configuration.platformApi){ - this.analytics.PlatformApi.setPlatformAPI(this.configuration.platformApi) + this.analytics.PlatformApi.setPlatformAPI(mapPlatformAPI(this.configuration.platformApi)) if (this.configuration.debug) console.log(`[COMSCORE] Set the Platform API to ${this.configuration.platformApi}`) } else { this.analytics.PlatformApi.setPlatformAPI(this.analytics.PlatformAPIs.html5) @@ -99,4 +99,41 @@ export class ComscoreConnector { destroy(): void { this.streamingAnalyticsIntegration.destroy(); } -} \ No newline at end of file +} + +function mapPlatformAPI(platformApi: ComscorePlatformAPIs): ns_.analytics.PlatformAPIs { + switch (platformApi) { + case ComscorePlatformAPIs.SmartTV: + return ns_.analytics.PlatformAPIs.SmartTV; + case ComscorePlatformAPIs.Netcast: + return ns_.analytics.PlatformAPIs.Netcast; + case ComscorePlatformAPIs.Cordova: + return ns_.analytics.PlatformAPIs.Cordova; + case ComscorePlatformAPIs.Trilithium: + return ns_.analytics.PlatformAPIs.Trilithium; + case ComscorePlatformAPIs.AppleTV: + return ns_.analytics.PlatformAPIs.AppleTV; + case ComscorePlatformAPIs.Chromecast: + return ns_.analytics.PlatformAPIs.Chromecast; + case ComscorePlatformAPIs.Xbox: + return ns_.analytics.PlatformAPIs.Xbox; + case ComscorePlatformAPIs.webOS: + return ns_.analytics.PlatformAPIs.webOS; + case ComscorePlatformAPIs.tvOS: + return ns_.analytics.PlatformAPIs.tvOS; + case ComscorePlatformAPIs.nodejs: + return ns_.analytics.PlatformAPIs.nodejs; + case ComscorePlatformAPIs.html5: + return ns_.analytics.PlatformAPIs.html5; + case ComscorePlatformAPIs.JSMAF: + return ns_.analytics.PlatformAPIs.JSMAF; + case ComscorePlatformAPIs.Skeleton: + return ns_.analytics.PlatformAPIs.Skeleton; + case ComscorePlatformAPIs.WebBrowser: + return ns_.analytics.PlatformAPIs.WebBrowser; + case ComscorePlatformAPIs.SamsungTizenTV: + return ns_.analytics.PlatformAPIs.SamsungTizenTV; + default: + return ns_.analytics.PlatformAPIs.html5; + } +} From d6b8e547f69c7e1f48e70c3df8471d26bfabb4a9 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Sat, 14 Sep 2024 22:28:29 +0200 Subject: [PATCH 19/26] include tizen platform api --- comscore/src/comscore/ComScore.d.ts | 507 ++++++++++++++-------------- 1 file changed, 253 insertions(+), 254 deletions(-) diff --git a/comscore/src/comscore/ComScore.d.ts b/comscore/src/comscore/ComScore.d.ts index de71766..9af99ab 100644 --- a/comscore/src/comscore/ComScore.d.ts +++ b/comscore/src/comscore/ComScore.d.ts @@ -1,265 +1,264 @@ declare namespace ns_ { namespace analytics { - enum ConnectivityType { - UNKNOWN, - UNAVAILABLE, - DISCONNECTED, - CONNECTED, - ETHERNET, - WIFI, - WWAN, - BLUETOOTH, - EMULATOR - } - - enum PlatformAPIs { - SmartTV, - Netcast, - Cordova, - Trilithium, - AppleTV, - Chromecast, - Xbox, - webOS, - tvOS, - nodejs, - html5, - JSMAF, - Skeleton, - WebBrowser - } - - namespace PlatformApi { - function setPlatformAPI(platformApi: PlatformAPIs): void; - function setPlatformAPI(platformApi: PlatformAPIs, interfaceObject: unknown): void; - function setPlatformApi(platformApi: PlatformAPIs, interfaceObject: unknown): void; - } - - class StreamingAnalytics { - setMediaPlayerName(name: string): void; - setMediaPlayerVersion(version: string): void; - createPlaybackSession(): void - getPlaybackSessionId(): void - loopPlaybackSession(): void - notifyBufferStart(): void - notifyBufferStop(): void - notifyChangePlaybackRate(rate: number): void; - notifyEnd(): void - notifyPause(): void - notifyPlay(): void - notifySeekStart(): void - setDvrWindowLength(length: number): void; - setImplementationId(id: string): void; - setMetadata(metadata: any): void; - setProjectId(id: string): void; - startFromDvrWindowOffset(offset: number): void; - startFromPosition(position: number): void; - startFromSegment(segment: any): void; - constructor(); - } - - namespace StreamingAnalytics { - namespace AdvertisementMetadata { - export enum AdvertisementType { - ON_DEMAND_PRE_ROLL, - ON_DEMAND_MID_ROLL, - ON_DEMAND_POST_ROLL, - LIVE, - BRANDED_ON_DEMAND_PRE_ROLL, - BRANDED_ON_DEMAND_MID_ROLL, - BRANDED_ON_DEMAND_POST_ROLL, - BRANDED_AS_CONTENT, - BRANDED_DURING_LIVE, - OTHER, - } + enum ConnectivityType { + UNKNOWN, + UNAVAILABLE, + DISCONNECTED, + CONNECTED, + ETHERNET, + WIFI, + WWAN, + BLUETOOTH, + EMULATOR + } - export enum AdvertisementDeliveryType { - NATIONAL, - LOCAL, - SYNDICATION - } - } - - class AdvertisementMetadata { - addCustomLabels(labels: any): void; - classifyAsAudioStream(isAudio: boolean): void; - setCallToActionUrl(url: string): void; - setClipUrl(url: string): void; - setDeliveryType(type: StreamingAnalytics.AdvertisementMetadata.AdvertisementDeliveryType): void; - setLength(length: number): void; - setMediaType(type: StreamingAnalytics.AdvertisementMetadata.AdvertisementType): void; - setOwner(owner: string): void; - setPlacementId(id: string): void; - setRelatedContentMetadata(metadata: any): void; - setServer(server: string): void; - setServerCampaignId(id: string): void; - setSiteId(id: string): void; - setTitle(title: string): void; - setUniqueId(id: string): void; - setVideoDimensions(width: number, height: number): void; - - getMetadataLabels(): any; - - - constructor(); - } - - namespace ContentMetadata { - - export enum ContentDeliveryAdvertisementCapability { - NONE, - DYNAMIC_LOAD, - DYNAMIC_REPLACEMENT, - LINEAR_1DAY, - LINEAR_2DAY, - LINEAR_3DAY, - LINEAR_4DAY, - LINEAR_5DAY, - LINEAR_6DAY, - LINEAR_7DAY - } - - export enum ContentDeliveryComposition { - CLEAN, - EMBED - } - - export enum ContentDeliveryMode { - LINEAR, - ON_DEMAND - } - - export enum ContentDeliverySubscriptionType { - ADVERTISING, - PREMIUM, - SUBSCRIPTION, - TRADITIONAL_MVPD, - TRANSACTIONAL, - VIRTUAL_MVPD, - } - - export enum ContentDistributionModel { - EXCLUSIVELY_ONLINE, - TV_AND_ONLINE - } - - export enum ContentFeedType { - EAST_HD, - EAST_SD, - OTHER, - WEST_HD, - WEST_SD - } - - export enum ContentMediaFormat { - EXTRA_EPISODE, - EXTRA_GENERIC, - EXTRA_MOVIE, - FULL_CONTENT_EPISODE, - FULL_CONTENT_GENERIC, - FULL_CONTENT_MOVIE, - PARTIAL_CONTENT_EPISODE, - PARTIAL_CONTENT_GENERIC, - PARTIAL_CONTENT_MOVIE, - PREVIEW_EPISODE, - PREVIEW_GENERIC, - PREVIEW_MOVIE - } - - export enum ContentType { - LONG_FORM_ON_DEMAND, - SHORT_FORM_ON_DEMAND, - LIVE, - USER_GENERATED_SHORT_FORM_ON_DEMAND, - USER_GENERATED_LONG_FORM_ON_DEMAND, - USER_GENERATED_LIVE, - BUMPER, - OTHER, - } + enum PlatformAPIs { + SmartTV, + Netcast, + Cordova, + Trilithium, + AppleTV, + Chromecast, + Xbox, + webOS, + tvOS, + nodejs, + html5, + JSMAF, + Skeleton, + WebBrowser, + SamsungTizenTV + } + + namespace PlatformApi { + function setPlatformAPI(platformApi: PlatformAPIs): void; + function setPlatformAPI(platformApi: PlatformAPIs, interfaceObject: unknown): void; + function setPlatformApi(platformApi: PlatformAPIs, interfaceObject: unknown): void; } - - class ContentMetadata { - addCustomLabels(labels: any): void; - carryTvAdvertisementLoad(carriesTvAdvertisementLoad: boolean): void; - classifyAsAudioStream(audioStream: boolean): void; - classifyAsCompleteEpisode(completeEpisode: boolean): void; - setClipUrl(url: string): void; - setDateOfDigitalAiring(year: number, month: number, day: number): void; - setDateOfProduction(year: number, month: number, day: number): void; - setDateOfTvAiring(year: number, month: number, day: number): void; - setDeliveryAdvertisementCapability(value: StreamingAnalytics.ContentMetadata.ContentDeliveryAdvertisementCapability): void; - setDeliveryComposition(value: StreamingAnalytics.ContentMetadata.ContentDeliveryComposition): void; - setDeliveryMode(value: StreamingAnalytics.ContentMetadata.ContentDeliveryMode): void; - setDeliverySubscriptionType(value: StreamingAnalytics.ContentMetadata.ContentDeliverySubscriptionType): void; - setDictionaryClassificationC3(value: string): void; - setDictionaryClassificationC4(value: string): void; - setDictionaryClassificationC6(value: string): void; - setDistributionModel(value: StreamingAnalytics.ContentMetadata.ContentDistributionModel): void; - setEpisodeId(id: string): void; - setEpisodeNumber(episodeNumber: string): void; - setEpisodeSeasonNumber(seasonNumber: string): void; - setEpisodeTitle(title: string): void; - setFeedType(value: StreamingAnalytics.ContentMetadata.ContentFeedType): void; - setGenreId(id: string): void; - setGenreName(name: string): void; - setLength(length: number): void; - setMediaFormat(value: StreamingAnalytics.ContentMetadata.ContentMediaFormat): void; - setMediaType(value: StreamingAnalytics.ContentMetadata.ContentType): void; - setNetworkAffiliate(code: string): void; - setPlaylistTitle(title: string): void; - setProgramId(id: string): void; - setProgramTitle(title: string): void; - setPublisherName(name: string): void; - setStationCode(code: string): void; - setStationTitle(title: string): void; - setTimeOfDigitalAiring(hours: number, minutes: number): void; - setTimeOfProduction(hours: number, minutes: number): void; - setTimeOfTvAiring(hours: number, minutes: number): void; - setTotalSegments(total: number): void; - setUniqueId(id: string): void; - setVideoDimensions(width: number, height: number): void; - - getMetadataLabels(): any; - + + class StreamingAnalytics { + setMediaPlayerName(name: string): void; + setMediaPlayerVersion(version: string): void; + createPlaybackSession(): void; + getPlaybackSessionId(): void; + loopPlaybackSession(): void; + notifyBufferStart(): void; + notifyBufferStop(): void; + notifyChangePlaybackRate(rate: number): void; + notifyEnd(): void; + notifyPause(): void; + notifyPlay(): void; + notifySeekStart(): void; + setDvrWindowLength(length: number): void; + setImplementationId(id: string): void; + setMetadata(metadata: any): void; + setProjectId(id: string): void; + startFromDvrWindowOffset(offset: number): void; + startFromPosition(position: number): void; + startFromSegment(segment: any): void; constructor(); + } + + namespace StreamingAnalytics { + namespace AdvertisementMetadata { + export enum AdvertisementType { + ON_DEMAND_PRE_ROLL, + ON_DEMAND_MID_ROLL, + ON_DEMAND_POST_ROLL, + LIVE, + BRANDED_ON_DEMAND_PRE_ROLL, + BRANDED_ON_DEMAND_MID_ROLL, + BRANDED_ON_DEMAND_POST_ROLL, + BRANDED_AS_CONTENT, + BRANDED_DURING_LIVE, + OTHER + } + + export enum AdvertisementDeliveryType { + NATIONAL, + LOCAL, + SYNDICATION + } + } + + class AdvertisementMetadata { + addCustomLabels(labels: any): void; + classifyAsAudioStream(isAudio: boolean): void; + setCallToActionUrl(url: string): void; + setClipUrl(url: string): void; + setDeliveryType(type: StreamingAnalytics.AdvertisementMetadata.AdvertisementDeliveryType): void; + setLength(length: number): void; + setMediaType(type: StreamingAnalytics.AdvertisementMetadata.AdvertisementType): void; + setOwner(owner: string): void; + setPlacementId(id: string): void; + setRelatedContentMetadata(metadata: any): void; + setServer(server: string): void; + setServerCampaignId(id: string): void; + setSiteId(id: string): void; + setTitle(title: string): void; + setUniqueId(id: string): void; + setVideoDimensions(width: number, height: number): void; + + getMetadataLabels(): any; + + constructor(); + } + + namespace ContentMetadata { + export enum ContentDeliveryAdvertisementCapability { + NONE, + DYNAMIC_LOAD, + DYNAMIC_REPLACEMENT, + LINEAR_1DAY, + LINEAR_2DAY, + LINEAR_3DAY, + LINEAR_4DAY, + LINEAR_5DAY, + LINEAR_6DAY, + LINEAR_7DAY + } + + export enum ContentDeliveryComposition { + CLEAN, + EMBED + } + + export enum ContentDeliveryMode { + LINEAR, + ON_DEMAND + } + + export enum ContentDeliverySubscriptionType { + ADVERTISING, + PREMIUM, + SUBSCRIPTION, + TRADITIONAL_MVPD, + TRANSACTIONAL, + VIRTUAL_MVPD + } + + export enum ContentDistributionModel { + EXCLUSIVELY_ONLINE, + TV_AND_ONLINE + } + + export enum ContentFeedType { + EAST_HD, + EAST_SD, + OTHER, + WEST_HD, + WEST_SD + } + export enum ContentMediaFormat { + EXTRA_EPISODE, + EXTRA_GENERIC, + EXTRA_MOVIE, + FULL_CONTENT_EPISODE, + FULL_CONTENT_GENERIC, + FULL_CONTENT_MOVIE, + PARTIAL_CONTENT_EPISODE, + PARTIAL_CONTENT_GENERIC, + PARTIAL_CONTENT_MOVIE, + PREVIEW_EPISODE, + PREVIEW_GENERIC, + PREVIEW_MOVIE + } + + export enum ContentType { + LONG_FORM_ON_DEMAND, + SHORT_FORM_ON_DEMAND, + LIVE, + USER_GENERATED_SHORT_FORM_ON_DEMAND, + USER_GENERATED_LONG_FORM_ON_DEMAND, + USER_GENERATED_LIVE, + BUMPER, + OTHER + } + } + + class ContentMetadata { + addCustomLabels(labels: any): void; + carryTvAdvertisementLoad(carriesTvAdvertisementLoad: boolean): void; + classifyAsAudioStream(audioStream: boolean): void; + classifyAsCompleteEpisode(completeEpisode: boolean): void; + setClipUrl(url: string): void; + setDateOfDigitalAiring(year: number, month: number, day: number): void; + setDateOfProduction(year: number, month: number, day: number): void; + setDateOfTvAiring(year: number, month: number, day: number): void; + setDeliveryAdvertisementCapability( + value: StreamingAnalytics.ContentMetadata.ContentDeliveryAdvertisementCapability + ): void; + setDeliveryComposition(value: StreamingAnalytics.ContentMetadata.ContentDeliveryComposition): void; + setDeliveryMode(value: StreamingAnalytics.ContentMetadata.ContentDeliveryMode): void; + setDeliverySubscriptionType( + value: StreamingAnalytics.ContentMetadata.ContentDeliverySubscriptionType + ): void; + setDictionaryClassificationC3(value: string): void; + setDictionaryClassificationC4(value: string): void; + setDictionaryClassificationC6(value: string): void; + setDistributionModel(value: StreamingAnalytics.ContentMetadata.ContentDistributionModel): void; + setEpisodeId(id: string): void; + setEpisodeNumber(episodeNumber: string): void; + setEpisodeSeasonNumber(seasonNumber: string): void; + setEpisodeTitle(title: string): void; + setFeedType(value: StreamingAnalytics.ContentMetadata.ContentFeedType): void; + setGenreId(id: string): void; + setGenreName(name: string): void; + setLength(length: number): void; + setMediaFormat(value: StreamingAnalytics.ContentMetadata.ContentMediaFormat): void; + setMediaType(value: StreamingAnalytics.ContentMetadata.ContentType): void; + setNetworkAffiliate(code: string): void; + setPlaylistTitle(title: string): void; + setProgramId(id: string): void; + setProgramTitle(title: string): void; + setPublisherName(name: string): void; + setStationCode(code: string): void; + setStationTitle(title: string): void; + setTimeOfDigitalAiring(hours: number, minutes: number): void; + setTimeOfProduction(hours: number, minutes: number): void; + setTimeOfTvAiring(hours: number, minutes: number): void; + setTotalSegments(total: number): void; + setUniqueId(id: string): void; + setVideoDimensions(width: number, height: number): void; + + getMetadataLabels(): any; + + constructor(); + } } - } - - namespace configuration { - function setApplicationName(name: string): void; - - function setApplicationVersion(name: string): void; - - function addClient(config: PublisherConfiguration): void; - - function getPublisherConfiguration(id: string): any; - - function setPersistentLabel(name: string, value: any): void; - - function addPersistentLabels(labels: any): void; - - function enableImplementationValidationMode(): void; - - function enableChildDirectedApplicationMode(): void; - - class PublisherConfiguration { - publisherId: string; - constructor({ }: any) + namespace configuration { + function setApplicationName(name: string): void; + + function setApplicationVersion(name: string): void; + + function addClient(config: PublisherConfiguration): void; + + function getPublisherConfiguration(id: string): any; + + function setPersistentLabel(name: string, value: any): void; + + function addPersistentLabels(labels: any): void; + + function enableImplementationValidationMode(): void; + + function enableChildDirectedApplicationMode(): void; + + class PublisherConfiguration { + publisherId: string; + constructor({}: any); + } } - } - - function notifyHiddenEvent(): void; - - function notifyEnterForeground(): void; - - function notifyExitForeground(): void; - - function close(): void; - - function start(): void; + function notifyHiddenEvent(): void; + + function notifyEnterForeground(): void; + + function notifyExitForeground(): void; + + function close(): void; + + function start(): void; } - } - \ No newline at end of file +} From 04c4c9c41c9a64d2e0effe3c88c927ed95522b5d Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Mon, 16 Sep 2024 14:34:04 +0200 Subject: [PATCH 20/26] add changeset for missing related content metadata bugfix --- .changeset/rare-cycles-give.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/rare-cycles-give.md diff --git a/.changeset/rare-cycles-give.md b/.changeset/rare-cycles-give.md new file mode 100644 index 0000000..329b7c9 --- /dev/null +++ b/.changeset/rare-cycles-give.md @@ -0,0 +1,5 @@ +--- +"@theoplayer/comscore-connector-web": patch +--- + +Fixed an issue where no content metadata was reported during a pre-roll ad. From 12f4d8135b8da3a36f6a32c20b12ea911bfde259 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Wed, 18 Sep 2024 07:34:21 +0200 Subject: [PATCH 21/26] only ignore playing events before pre-roll breaks that have ads --- .../ComscoreStreamingAnalyticsTHEOIntegration.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts index f2486f9..244e2b0 100644 --- a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts +++ b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts @@ -542,8 +542,15 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { } }; - private isBeforePreRoll = (): boolean => - this.player.ads?.scheduledAdBreaks.length ? this.player.ads?.scheduledAdBreaks[0].timeOffset === 0 : false; + private isBeforePreRoll = (): boolean => { + const hasScheduledAdBreaks = this.player.ads?.scheduledAdBreaks.length !== 0; + const firstScheduledAdBreakIsPreroll = + hasScheduledAdBreaks && this.player.ads?.scheduledAdBreaks[0].timeOffset === 0; + const hasScheduledPrerollWithAds = + firstScheduledAdBreakIsPreroll && this.player.ads?.scheduledAdBreaks[0].ads?.length !== 0; + return hasScheduledPrerollWithAds; + }; + // private isAfterPostRoll = () => this.lastAdBreakOffset && this.lastAdBreakOffset < 0 && this.player.duration - this.player.currentTime < 1 private isAfterPostRoll = (): boolean => this.lastAdBreakType ? this.lastAdBreakType === AdBreakType.POST_ROLL : false; From 8b29b08a028d0f0597cd8b1da00b553cb00fad77 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Wed, 18 Sep 2024 07:34:31 +0200 Subject: [PATCH 22/26] prettier --- ...mscoreStreamingAnalyticsTHEOIntegration.ts | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts index 244e2b0..965f28e 100644 --- a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts +++ b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts @@ -58,8 +58,8 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { private contentMetadata: ns_.analytics.StreamingAnalytics.ContentMetadata | null = null; // Main content related fields for use outside of event handlers - private dvrWindowLengthMs: number | undefined = undefined - private dvrWindowOffsetMs: number | undefined = undefined + private dvrWindowLengthMs: number | undefined = undefined; + private dvrWindowOffsetMs: number | undefined = undefined; // Advertisement related fields for use outside of ad event handlers private inAd: boolean = false; @@ -178,10 +178,14 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { this.state = ComscoreState.VIDEO; this.setContentMetadata(); if (this.dvrWindowLengthMs) { - this.streamingAnalytics.setDvrWindowLength(this.dvrWindowLengthMs) - if (this.configuration.debug && LOG_STREAMINGANALYTICS) console.log(`[COMSCORE - StreamingAnalytics] setDvrWindowLength ${this.dvrWindowLengthMs}`); - this.streamingAnalytics.startFromDvrWindowOffset(this.dvrWindowOffsetMs ?? 0) - if (this.configuration.debug && LOG_STREAMINGANALYTICS) console.log(`[COMSCORE - StreamingAnalytics] startFromDvrWindowOffset ${this.dvrWindowOffsetMs}`); + this.streamingAnalytics.setDvrWindowLength(this.dvrWindowLengthMs); + if (this.configuration.debug && LOG_STREAMINGANALYTICS) + console.log(`[COMSCORE - StreamingAnalytics] setDvrWindowLength ${this.dvrWindowLengthMs}`); + this.streamingAnalytics.startFromDvrWindowOffset(this.dvrWindowOffsetMs ?? 0); + if (this.configuration.debug && LOG_STREAMINGANALYTICS) + console.log( + `[COMSCORE - StreamingAnalytics] startFromDvrWindowOffset ${this.dvrWindowOffsetMs}` + ); } break; case ComscoreState.ADVERTISEMENT: @@ -193,10 +197,14 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { this.state = ComscoreState.VIDEO; this.setContentMetadata(); if (this.dvrWindowLengthMs) { - this.streamingAnalytics.setDvrWindowLength(this.dvrWindowLengthMs) - if (this.configuration.debug && LOG_STREAMINGANALYTICS) console.log(`[COMSCORE - StreamingAnalytics] setDvrWindowLength ${this.dvrWindowLengthMs}`); - this.streamingAnalytics.startFromDvrWindowOffset(this.dvrWindowOffsetMs ?? 0) - if (this.configuration.debug && LOG_STREAMINGANALYTICS) console.log(`[COMSCORE - StreamingAnalytics] startFromDvrWindowOffset ${this.dvrWindowOffsetMs}`); + this.streamingAnalytics.setDvrWindowLength(this.dvrWindowLengthMs); + if (this.configuration.debug && LOG_STREAMINGANALYTICS) + console.log(`[COMSCORE - StreamingAnalytics] setDvrWindowLength ${this.dvrWindowLengthMs}`); + this.streamingAnalytics.startFromDvrWindowOffset(this.dvrWindowOffsetMs ?? 0); + if (this.configuration.debug && LOG_STREAMINGANALYTICS) + console.log( + `[COMSCORE - StreamingAnalytics] startFromDvrWindowOffset ${this.dvrWindowOffsetMs}` + ); } break; case ComscoreState.VIDEO_PAUSED: @@ -388,8 +396,9 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { const dvrWindowStart = seekable.start(0); const dvrWindowLengthInSeconds = dvrWindowEnd - dvrWindowStart; if (dvrWindowLengthInSeconds) { - this.dvrWindowLengthMs = toMilliSeconds(dvrWindowLengthInSeconds) - if (this.state === ComscoreState.VIDEO || this.state === ComscoreState.VIDEO_PAUSED) this.streamingAnalytics.setDvrWindowLength(this.dvrWindowLengthMs) + this.dvrWindowLengthMs = toMilliSeconds(dvrWindowLengthInSeconds); + if (this.state === ComscoreState.VIDEO || this.state === ComscoreState.VIDEO_PAUSED) + this.streamingAnalytics.setDvrWindowLength(this.dvrWindowLengthMs); } else if (this.configuration.debug) console.log(`[COMSCORE] DVR window length was not > 0`); } } catch (error) { @@ -427,17 +436,15 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { } const dvrWindowEnd = seekable.end(seekable.length - 1); const dvrWindowOffsetInSeconds = dvrWindowEnd - currentTime; - this.dvrWindowOffsetMs = toMilliSeconds(dvrWindowOffsetInSeconds) + this.dvrWindowOffsetMs = toMilliSeconds(dvrWindowOffsetInSeconds); if (this.state === ComscoreState.VIDEO || this.state === ComscoreState.VIDEO_PAUSED) { this.streamingAnalytics.startFromDvrWindowOffset(this.dvrWindowOffsetMs); if (this.configuration.debug && LOG_STREAMINGANALYTICS) - console.log( - `[COMSCORE - StreamingAnalytics] startFromDvrWindowOffset ${this.dvrWindowOffsetMs}` - ); + console.log(`[COMSCORE - StreamingAnalytics] startFromDvrWindowOffset ${this.dvrWindowOffsetMs}`); } } else { if (this.configuration.debug) console.log(`[COMSCORE] seeked in a VOD stream`); - const currentTimeInMilliSeconds = toMilliSeconds(currentTime) + const currentTimeInMilliSeconds = toMilliSeconds(currentTime); this.streamingAnalytics.startFromPosition(currentTimeInMilliSeconds); if (this.configuration.debug && LOG_STREAMINGANALYTICS) console.log(`[COMSCORE - StreamingAnalytics] startFromPosition ${currentTimeInMilliSeconds}`); @@ -482,7 +489,7 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { if (this.configuration.debug && LOG_THEOPLAYER_EVENTS) console.log(`[COMSCORE - THEOplayer EVENTS] ${event.type} event`); this.transitionToStopped(); - } + }; private onAdBreakEnd = (event: AdBreakEvent<'adbreakend'>) => { if (this.configuration.debug && LOG_THEOPLAYER_EVENTS) From ef6bfa39b2d26d137ba8975c18c8a032f5a0d12f Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Wed, 18 Sep 2024 07:35:42 +0200 Subject: [PATCH 23/26] add changeset for empty pre-roll issue --- .changeset/metal-ties-draw.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/metal-ties-draw.md diff --git a/.changeset/metal-ties-draw.md b/.changeset/metal-ties-draw.md new file mode 100644 index 0000000..9310f4a --- /dev/null +++ b/.changeset/metal-ties-draw.md @@ -0,0 +1,5 @@ +--- +"@theoplayer/comscore-connector-web": patch +--- + +Fixed an issue where playback of the main content wouldn't get reported if Google IMA returned an empty pre-roll ad break. From 04e1f18e372113a9b65ae62edeca24711a70d476 Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Thu, 26 Sep 2024 16:42:43 +0200 Subject: [PATCH 24/26] remove empty comment --- comscore/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/comscore/README.md b/comscore/README.md index c67ea9c..83e18ab 100644 --- a/comscore/README.md +++ b/comscore/README.md @@ -64,7 +64,7 @@ analytics.PlatformApi.setPlatformApi(analytics.PlatformApi.PlatformApis.Skeleton // Execute a function with platform-specific code to retrieve up-to-date information. runPlatformSpecificCodeToRetrieveValues(onSuccessCallback, onErrorCallback); } - // + // Other overridden PlatformAPI methods, as needed. }); ``` From 56415d95f40d2d1981e46b758e1ed45bf7553d9f Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Thu, 26 Sep 2024 20:25:05 +0200 Subject: [PATCH 25/26] return early if the ads feature is not enabled on the player sdk --- .../src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts index 965f28e..c042964 100644 --- a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts +++ b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts @@ -550,6 +550,7 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { }; private isBeforePreRoll = (): boolean => { + if (!this.player.ads) return false; const hasScheduledAdBreaks = this.player.ads?.scheduledAdBreaks.length !== 0; const firstScheduledAdBreakIsPreroll = hasScheduledAdBreaks && this.player.ads?.scheduledAdBreaks[0].timeOffset === 0; From 955b85368a60b7d9fd6a03eb84bd6d3b0bffdf6a Mon Sep 17 00:00:00 2001 From: Wonne Joosen Date: Thu, 26 Sep 2024 20:44:18 +0200 Subject: [PATCH 26/26] separate function for setting dvr window length and offset --- ...mscoreStreamingAnalyticsTHEOIntegration.ts | 33 ++++++++----------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts index c042964..ccfaf1b 100644 --- a/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts +++ b/comscore/src/integration/ComscoreStreamingAnalyticsTHEOIntegration.ts @@ -177,16 +177,7 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { console.log(`[COMSCORE - STATE] State change ${this.state} -> VIDEO`); this.state = ComscoreState.VIDEO; this.setContentMetadata(); - if (this.dvrWindowLengthMs) { - this.streamingAnalytics.setDvrWindowLength(this.dvrWindowLengthMs); - if (this.configuration.debug && LOG_STREAMINGANALYTICS) - console.log(`[COMSCORE - StreamingAnalytics] setDvrWindowLength ${this.dvrWindowLengthMs}`); - this.streamingAnalytics.startFromDvrWindowOffset(this.dvrWindowOffsetMs ?? 0); - if (this.configuration.debug && LOG_STREAMINGANALYTICS) - console.log( - `[COMSCORE - StreamingAnalytics] startFromDvrWindowOffset ${this.dvrWindowOffsetMs}` - ); - } + this.maybeReportDvrFields(); break; case ComscoreState.ADVERTISEMENT: case ComscoreState.ADVERTISEMENT_PAUSED: @@ -196,16 +187,7 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { console.log(`[COMSCORE - STATE] State change ${this.state} -> VIDEO`); this.state = ComscoreState.VIDEO; this.setContentMetadata(); - if (this.dvrWindowLengthMs) { - this.streamingAnalytics.setDvrWindowLength(this.dvrWindowLengthMs); - if (this.configuration.debug && LOG_STREAMINGANALYTICS) - console.log(`[COMSCORE - StreamingAnalytics] setDvrWindowLength ${this.dvrWindowLengthMs}`); - this.streamingAnalytics.startFromDvrWindowOffset(this.dvrWindowOffsetMs ?? 0); - if (this.configuration.debug && LOG_STREAMINGANALYTICS) - console.log( - `[COMSCORE - StreamingAnalytics] startFromDvrWindowOffset ${this.dvrWindowOffsetMs}` - ); - } + this.maybeReportDvrFields(); break; case ComscoreState.VIDEO_PAUSED: if (this.configuration.debug && LOG_STATE_CHANGES) @@ -519,6 +501,17 @@ export class ComscoreStreamingAnalyticsTHEOIntegration { } }; + private maybeReportDvrFields = () => { + if (this.dvrWindowLengthMs) { + this.streamingAnalytics.setDvrWindowLength(this.dvrWindowLengthMs); + if (this.configuration.debug && LOG_STREAMINGANALYTICS) + console.log(`[COMSCORE - StreamingAnalytics] setDvrWindowLength ${this.dvrWindowLengthMs}`); + this.streamingAnalytics.startFromDvrWindowOffset(this.dvrWindowOffsetMs ?? 0); + if (this.configuration.debug && LOG_STREAMINGANALYTICS) + console.log(`[COMSCORE - StreamingAnalytics] startFromDvrWindowOffset ${this.dvrWindowOffsetMs}`); + } + }; + private findAdBreakType = (offset: number, maxDuration: number, integration: string): AdBreakType => { if (offset === 0) { if (this.configuration.debug) console.log('[COMSCORE] Mark as PRE_ROLL');