-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from THEOplayer/nielsen
Nielsen
- Loading branch information
Showing
27 changed files
with
506 additions
and
121 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@theoplayer/nielsen-connector-web": minor | ||
--- | ||
|
||
Updated to be compatible with THEOplayer `6.X`. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,4 @@ | ||
node_modules/ | ||
|
||
# Generated by MacOS | ||
.DS_Store |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
File renamed without changes.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,7 @@ | |
"dist/", | ||
"CHANGELOG.md", | ||
"README.md", | ||
"LICENSE.md", | ||
"package.json" | ||
], | ||
"dependencies": { | ||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Node artifact files | ||
node_modules/ | ||
lib/ | ||
dist/ | ||
|
||
# Generated by MacOS | ||
.DS_Store | ||
|
||
# Generated by Windows | ||
Thumbs.db |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# @theoplayer/nielsen-connector-web | ||
|
||
## 1.0.0 | ||
|
||
### ✨ Features | ||
|
||
- Initial release |
File renamed without changes.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# Nielsen Web Connector | ||
|
||
A connector implementing Nielsen with THEOplayer. | ||
|
||
## Installation | ||
|
||
```sh | ||
npm install @theoplayer/nielsen-connector-web | ||
``` | ||
|
||
## Usage | ||
|
||
### Configuring the connector | ||
|
||
Create the connector by providing the `THEOplayer` instance, the Nielsen App ID, the channelName for the asset | ||
and optionally some Nielsen configuration. | ||
|
||
```js | ||
import {NielsenConnector} from "../../dist/THEOplayerNielsenConnector"; | ||
|
||
const appId = '<your app ID>'; | ||
const channelName = '<your channel name>'; | ||
// Optional | ||
const options: NielsenOptions = { | ||
containerId: 'THEOplayer', | ||
optout: false | ||
} | ||
const nielsenConnector = new NielsenConnector(player, appId, channelName, options); | ||
``` | ||
|
||
The `NielsenOptions` can have the following fields: | ||
|
||
| Key | Value | | ||
|-----------------|-----------------------------------------------------------------| | ||
| ` containerId ` | HTML DOM element id of the player container. | | ||
| ` nol_sdkDebug` | Enables Debug Mode which allows output to be viewed in console. | | ||
| ` optout ` | Whether to opt-out of Nielsen Measurement. | | ||
|
||
### Passing metadata dynamically | ||
|
||
The connector allows updating the current asset's metadata at any time: | ||
|
||
```js | ||
const metadata = { | ||
['channelName']: 'newChannelName', | ||
['customTag1']: 'customValue1', | ||
['customTag2']: 'customValue2' | ||
} | ||
nielsenConnector.updateMetadata(metadata); | ||
``` |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
module.exports = { | ||
preset: "ts-jest", | ||
testEnvironment: "node" | ||
}; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"name": "@theoplayer/nielsen-connector-web", | ||
"version": "1.0.0", | ||
"description": "A connector implementing Nielsen with THEOplayer.", | ||
"main": "dist/THEOplayerNielsenConnector.umd.js", | ||
"module": "dist/THEOplayerNielsenConnector.esm.js", | ||
"types": "dist/THEOplayerNielsenConnector.d.ts", | ||
"exports": { | ||
".": { | ||
"types": "./dist/THEOplayerNielsenConnector.d.ts", | ||
"import": "./dist/THEOplayerNielsenConnector.esm.js", | ||
"require": "./dist/THEOplayerNielsenConnector.umd.js" | ||
}, | ||
"./dist/*": "./dist/*", | ||
"./package": "./package.json", | ||
"./package.json": "./package.json" | ||
}, | ||
"scripts": { | ||
"clean": "rimraf lib dist", | ||
"bundle": "rollup -c rollup.config.mjs", | ||
"build": "npm run clean && npm run bundle", | ||
"serve": "http-server", | ||
"test": "jest" | ||
}, | ||
"author": "THEO Technologies NV", | ||
"license": "MIT", | ||
"files": [ | ||
"dist/", | ||
"CHANGELOG.md", | ||
"README.md", | ||
"LICENSE.md", | ||
"package.json" | ||
], | ||
"peerDependencies": { | ||
"theoplayer": "^5.0.0 || ^6.0.0" | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import {getSharedBuildConfiguration} from "../tools/build.mjs"; | ||
import fs from "node:fs"; | ||
|
||
const {version} = JSON.parse(fs.readFileSync("./package.json", "utf8")); | ||
|
||
const fileName = "nielsen-connector"; | ||
const globalName = "THEOplayerNielsenConnector"; | ||
|
||
const banner = ` | ||
/** | ||
* Nielsen Web Connector v${version} | ||
*/`.trim(); | ||
|
||
export default getSharedBuildConfiguration(fileName, globalName, banner); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { NielsenConnector } from './integration/NielsenConnector'; | ||
export { NielsenOptions } from './nielsen/Types'; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { ChromelessPlayer } from 'theoplayer'; | ||
import { NielsenOptions } from '../nielsen/Types'; | ||
import { NielsenHandler } from './NielsenHandler'; | ||
|
||
export class NielsenConnector { | ||
private nielsenHandler: NielsenHandler; | ||
|
||
/** | ||
* Create NielsenConnector | ||
* | ||
* @param player THEOplayer instance. | ||
* @param appId UniqueID assigned to player/site. | ||
* @param instanceName User-defined string value for describing the player/site. | ||
* @param options Additional options. | ||
*/ | ||
constructor(player: ChromelessPlayer, appId: string, instanceName: string, options?: NielsenOptions) { | ||
this.nielsenHandler = new NielsenHandler(player, appId, instanceName, options); | ||
} | ||
|
||
updateMetadata(metadata: { [key: string]: string }): void { | ||
this.nielsenHandler.updateMetadata(metadata); | ||
} | ||
|
||
destroy() { | ||
this.nielsenHandler.destroy(); | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import { Ad, AddTrackEvent, ChromelessPlayer, TextTrack, TextTrackEnterCueEvent, VolumeChangeEvent } from 'theoplayer'; | ||
import { loadNielsenLibrary } from '../nielsen/NOLBUNDLE'; | ||
import { AdMetadata, ContentMetadata, NielsenOptions } from '../nielsen/Types'; | ||
import { getAdType } from '../utils/Util'; | ||
|
||
export class NielsenHandler { | ||
private player: ChromelessPlayer; | ||
|
||
private nSdkInstance: any; | ||
|
||
private sessionInProgress: boolean = false; | ||
|
||
private duration: number = NaN; | ||
|
||
constructor(player: ChromelessPlayer, appId: string, instanceName: string, options?: NielsenOptions) { | ||
this.player = player; | ||
this.nSdkInstance = loadNielsenLibrary(appId, instanceName, options); | ||
|
||
this.addEventListeners(); | ||
} | ||
|
||
updateMetadata(metadata: { [key: string]: string }): void { | ||
this.nSdkInstance.ggPM('updateMetadata', metadata); | ||
} | ||
|
||
private addEventListeners(): void { | ||
this.player.addEventListener('play', this.onPlay); | ||
this.player.addEventListener('ended', this.onEnd); | ||
this.player.addEventListener('sourcechange', this.onSourceChange); | ||
this.player.addEventListener('volumechange', this.onVolumeChange); | ||
this.player.addEventListener('loadedmetadata', this.onLoadMetadata); | ||
this.player.addEventListener('durationchange', this.onDurationChange); | ||
|
||
this.player.textTracks.addEventListener('addtrack', this.onAddTrack); | ||
|
||
if (this.player.ads) { | ||
this.player.ads.addEventListener('adbegin', this.onAdBegin); | ||
} | ||
|
||
window.addEventListener('beforeunload', this.onEnd); | ||
} | ||
|
||
private removeEventListeners(): void { | ||
this.player.removeEventListener('play', this.onPlay); | ||
this.player.removeEventListener('ended', this.onEnd); | ||
this.player.removeEventListener('sourcechange', this.onSourceChange); | ||
this.player.removeEventListener('volumechange', this.onVolumeChange); | ||
this.player.removeEventListener('loadedmetadata', this.onLoadMetadata); | ||
this.player.removeEventListener('durationchange', this.onDurationChange); | ||
|
||
this.player.textTracks.removeEventListener('addtrack', this.onAddTrack); | ||
|
||
if (this.player.ads) { | ||
this.player.ads.removeEventListener('adbegin', this.onAdBegin); | ||
} | ||
|
||
window.removeEventListener('beforeunload', this.onEnd); | ||
} | ||
|
||
private onPlay = () => { | ||
this.maybeSendPlayEvent(); | ||
}; | ||
|
||
private onEnd = () => { | ||
this.endSession(); | ||
}; | ||
|
||
private onSourceChange = () => { | ||
this.duration = NaN; | ||
this.endSession(); | ||
}; | ||
|
||
private onVolumeChange = (event: VolumeChangeEvent) => { | ||
const volumeLevel = this.player.muted ? 0 : event.volume * 100; | ||
this.nSdkInstance.ggPM('setVolume', volumeLevel); | ||
}; | ||
|
||
private onDurationChange = () => { | ||
this.duration = this.player.duration; | ||
this.maybeSendPlayEvent(); | ||
}; | ||
|
||
private onLoadMetadata = () => { | ||
const data: ContentMetadata = { | ||
type: 'content', | ||
adModel: '1' // Always '1' for DTVR | ||
}; | ||
this.nSdkInstance.ggPM('loadMetadata', data); | ||
}; | ||
|
||
private onAddTrack = (event: AddTrackEvent) => { | ||
if (event.track.kind === 'metadata') { | ||
const track = event.track as TextTrack; | ||
if (track.type === 'id3') { | ||
// || track.type === 'emsg') { | ||
if (track.mode === 'disabled') { | ||
track.mode = 'hidden'; | ||
} | ||
track.addEventListener('entercue', this.onEnterCue); | ||
} | ||
} | ||
}; | ||
|
||
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); | ||
} | ||
} else { | ||
// TODO emsg is not supported for now | ||
} | ||
}; | ||
|
||
private onAdBegin = () => { | ||
const currentAd = this.player.ads!.currentAds.filter((ad: Ad) => ad.type === 'linear'); | ||
const type = getAdType(this.player.ads!.currentAdBreak!); | ||
const adMetadata: AdMetadata = { | ||
type, | ||
assetid: currentAd[0].id! | ||
}; | ||
this.nSdkInstance.ggPM('loadMetadata', adMetadata); | ||
}; | ||
|
||
private maybeSendPlayEvent(): void { | ||
if (!this.sessionInProgress && !Number.isNaN(this.duration)) { | ||
this.sessionInProgress = true; | ||
const metadataObject = { | ||
channelName: this.player.src, | ||
length: this.duration | ||
}; | ||
this.nSdkInstance.ggPM('play', metadataObject); | ||
} | ||
} | ||
|
||
private endSession(): void { | ||
if (this.sessionInProgress) { | ||
this.sessionInProgress = false; | ||
this.nSdkInstance.ggPM('end', this.getPlayHeadPosition()); | ||
} | ||
} | ||
|
||
private getPlayHeadPosition(): string { | ||
return Math.floor(this.player.currentTime).toString(); | ||
} | ||
|
||
destroy() { | ||
this.removeEventListeners(); | ||
this.endSession(); | ||
} | ||
} |
Oops, something went wrong.