From 97384fa4eb9defe55874a22d60bfbca7bc040c94 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 22 Mar 2024 09:06:50 +0100 Subject: [PATCH 1/4] Add emsg cue handling --- nielsen/src/integration/NielsenHandler.ts | 56 ++++++++++++++++++++--- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/nielsen/src/integration/NielsenHandler.ts b/nielsen/src/integration/NielsenHandler.ts index fc544919..dbdc828d 100644 --- a/nielsen/src/integration/NielsenHandler.ts +++ b/nielsen/src/integration/NielsenHandler.ts @@ -3,6 +3,9 @@ import { loadNielsenLibrary } from '../nielsen/NOLBUNDLE'; import { AdMetadata, ContentMetadata, NielsenOptions } from '../nielsen/Types'; import { getAdType } from '../utils/Util'; +const EMSG_PRIV_SUFFIX = "PRIV{"; +const EMSG_PAYLOAD_SUFFIX = "payload="; + export class NielsenHandler { private player: ChromelessPlayer; @@ -12,6 +15,8 @@ export class NielsenHandler { private duration: number = NaN; + private decoder = new TextDecoder('utf-8'); + constructor(player: ChromelessPlayer, appId: string, instanceName: string, options?: NielsenOptions) { this.player = player; this.nSdkInstance = loadNielsenLibrary(appId, instanceName, options); @@ -91,8 +96,8 @@ export class NielsenHandler { private onAddTrack = (event: AddTrackEvent) => { if (event.track.kind === 'metadata') { const track = event.track as TextTrack; - if (track.type === 'id3') { - // || track.type === 'emsg') { + if (track.type === 'id3' || track.type === 'emsg') { + // Make sure we get cues. if (track.mode === 'disabled') { track.mode = 'hidden'; } @@ -103,15 +108,52 @@ export class NielsenHandler { private onEnterCue = (event: TextTrackEnterCueEvent) => { const { cue } = event; - if (cue.track.type === 'id3') { - if (cue.content.id === 'PRIV' && cue.content.ownerIdentifier.indexOf('www.nielsen.com') !== -1) { - this.nSdkInstance.ggPM('sendID3', cue.content.ownerIdentifier); + if (cue.content) { + if (cue.track.type === 'id3') { + this.handleNielsenId3Payload(cue.content); + } else if (cue.track.type === 'emsg') { + this.handleNielsenEmsgPayload(cue.content); } - } else { - // TODO emsg is not supported for now } }; + private handleNielsenId3Payload = (content: any) => { + if (content.id === 'PRIV' && content.ownerIdentifier.indexOf('www.nielsen.com') !== -1) { + this.nSdkInstance.ggPM('sendID3', content.ownerIdentifier); + } + } + + private handleNielsenEmsgPayload = (content: any) => { + const cueContentText = this.decoder.decode(content); + if (cueContentText.startsWith('type=nielsen_tag')) { + // extract payload + const base64Index = cueContentText.indexOf(EMSG_PAYLOAD_SUFFIX); + try { + if (base64Index !== -1) { + const base64Payload = cueContentText.substring(base64Index + EMSG_PAYLOAD_SUFFIX.length); + + // sanitise base64payload before decoding, remove null and %-encoded chars. + // eslint-disable-next-line no-control-regex + const sanitizedBase64Payload = base64Payload.replace(/\x00|%[0-9A-Fa-f]{2}/g, ''); + const payload = atob(sanitizedBase64Payload); + + // sanitise payload before submitting: + // - only allow printable characters within ASCII 32 to 126 range. + // - no character beyong the last digit. + // - drop everything before ID3 PRIV{ + let sanitizedPayload = payload.replace(/[^ -~]|\D+$/g, ''); + const privIndex = sanitizedPayload.indexOf(EMSG_PRIV_SUFFIX); + sanitizedPayload = privIndex !== -1 ? sanitizedPayload.substring(privIndex + EMSG_PRIV_SUFFIX.length) : sanitizedPayload; + + // send payload. Note that there is no separate method for sending emsg content. + this.nSdkInstance.ggPM('sendID3', sanitizedPayload); + } + } catch (error) { + console.error("NielsenConnector", "Failed to parse Nielsen payload", error); + } + } + } + private onAdBegin = () => { const currentAd = this.player.ads!.currentAds.filter((ad: Ad) => ad.type === 'linear'); const type = getAdType(this.player.ads!.currentAdBreak!); From d3cc6b5f3a07000c10e1f345ce6d78bdd764410a Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 22 Mar 2024 09:11:28 +0100 Subject: [PATCH 2/4] Fix nielsen test page --- nielsen/test/pages/main.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nielsen/test/pages/main.html b/nielsen/test/pages/main.html index 7e9b6f65..910e458c 100644 --- a/nielsen/test/pages/main.html +++ b/nielsen/test/pages/main.html @@ -5,7 +5,7 @@ Connector test page - +
From 571d3c157dfb13535b09e63b73ead24e16d46abe Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Fri, 22 Mar 2024 09:19:21 +0100 Subject: [PATCH 3/4] Add changeset --- .changeset/few-buttons-itch.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/few-buttons-itch.md diff --git a/.changeset/few-buttons-itch.md b/.changeset/few-buttons-itch.md new file mode 100644 index 00000000..d3df7e4f --- /dev/null +++ b/.changeset/few-buttons-itch.md @@ -0,0 +1,5 @@ +--- +"@theoplayer/nielsen-connector-web": patch +--- + +Added support for DASH emsg cue payloads. From 044dd06543359fd71d7c66bb2c681d2d528550c2 Mon Sep 17 00:00:00 2001 From: Tom Van Laerhoven Date: Wed, 27 Mar 2024 09:01:50 +0100 Subject: [PATCH 4/4] Fix typo --- nielsen/src/integration/NielsenHandler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nielsen/src/integration/NielsenHandler.ts b/nielsen/src/integration/NielsenHandler.ts index dbdc828d..f9e58c78 100644 --- a/nielsen/src/integration/NielsenHandler.ts +++ b/nielsen/src/integration/NielsenHandler.ts @@ -139,7 +139,7 @@ export class NielsenHandler { // sanitise payload before submitting: // - only allow printable characters within ASCII 32 to 126 range. - // - no character beyong the last digit. + // - no character beyond the last digit. // - drop everything before ID3 PRIV{ let sanitizedPayload = payload.replace(/[^ -~]|\D+$/g, ''); const privIndex = sanitizedPayload.indexOf(EMSG_PRIV_SUFFIX);