Skip to content

Commit

Permalink
Merge pull request #8 from THEOplayer/comscore
Browse files Browse the repository at this point in the history
Comscore Connector
  • Loading branch information
MattiasBuelens authored Apr 11, 2024
2 parents 295bd65 + 05e8db3 commit b81e132
Show file tree
Hide file tree
Showing 26 changed files with 2,154 additions and 8 deletions.
5 changes: 5 additions & 0 deletions .changeset/lemon-spoons-boil.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@theoplayer/comscore-connector-web": patch
---

Fixed multiple issues where the timing of reporting the DVR window length and the playhead's offset wrt the DVR window end was wrong if a LIVE stream with a CSAI pre-roll was set as the player source.
5 changes: 5 additions & 0 deletions .changeset/odd-scissors-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@theoplayer/comscore-connector-web": patch
---

Initial release to npm.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Using the available connectors allows you to augment the features delivered thro
| Connector | npm package | Source code |
|:----------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------|
| CMCD | [![@theoplayer/cmcd-connector-web](https://img.shields.io/npm/v/%40theoplayer%2Fcmcd-connector-web?label=%40theoplayer%2Fcmcd-connector-web)](https://npmjs.com/package/@theoplayer/cmcd-connector-web) | [cmcd](https://github.com/THEOplayer/web-connectors/tree/main/cmcd) |
| Comscore | [![@theoplayer/comscore-connector-web](https://img.shields.io/npm/v/%40theoplayer%2Fcomscore-connector-web?label=%40theoplayer%2Fcomscore-connector-web)](https://npmjs.com/package/@theoplayer/comscore-connector-web) | [comscore](https://github.com/THEOplayer/web-connectors/tree/main/comscore) |
| Conviva | [![@theoplayer/conviva-connector-web](https://img.shields.io/npm/v/%40theoplayer%2Fconviva-connector-web?label=%40theoplayer%2Fconviva-connector-web)](https://npmjs.com/package/@theoplayer/conviva-connector-web) | [conviva](https://github.com/THEOplayer/web-connectors/tree/main/conviva) |
| Nielsen | [![@theoplayer/nielsen-connector-web](https://img.shields.io/npm/v/%40theoplayer%2Fnielsen-connector-web?label=%40theoplayer%2Fnielsen-connector-web)](https://npmjs.com/package/@theoplayer/nielsen-connector-web) | [nielsen](https://github.com/THEOplayer/web-connectors/tree/main/nielsen) |
| Yospace | [![@theoplayer/yospace-connector-web](https://img.shields.io/npm/v/%40theoplayer%2Fyospace-connector-web?label=%40theoplayer%2Fyospace-connector-web)](https://npmjs.com/package/@theoplayer/yospace-connector-web) | [yospace](https://github.com/THEOplayer/web-connectors/tree/main/yospace) |
Expand Down
3 changes: 3 additions & 0 deletions cmcd/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"url": "git+https://github.com/THEOplayer/web-connectors.git",
"directory": "cmcd"
},
"bugs": {
"url": "https://github.com/THEOplayer/web-connectors/issues"
},
"homepage": "https://theoplayer.com/",
"module": "dist/cmcd-connector.esm.js",
"types": "dist/types/index.d.ts",
Expand Down
10 changes: 10 additions & 0 deletions comscore/.gitignore
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
7 changes: 7 additions & 0 deletions comscore/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# @theoplayer/comscore-connector-web

## 1.0.21

### ✨ Features

- Initial release as a connector
110 changes: 110 additions & 0 deletions comscore/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# comscore-connector-web

The Comscore connector provides a Comscore integration for THEOplayer.

## Installation

```sh
npm install @theoplayer/comscore-connector-web
```

This connector depends on the JavaScript ComScore SDK, which should be loaded and available in the global scope before the connector. Get it from your ComScore dashboard or talk to a ComScore representative. This connector was developed and tested with versions 7.2.0.200214 and 7.6.1.210506

```html
<script src="/path/to/comscore.js">
```
## Usage
### Configuring the connector
Create the connector by providing the `THEOplayer` instance, a ComscoreConfiguration (which contains your publisher id, also referred to as the c2 value) and the ComscoreMetadata of the first source being set to the player. You can change the metadata dynamically throughout the lifecycle of the connector.
```js
import { ComscoreConnector } from '../../dist/comscore-connector.esm.js';
const comscoreConfig = {
publisherId: '<your publisher id>',
applicationName: 'Test App',
userConsent: '1',
debug: true
};
const comscoreMetadata = {
mediaType: 'longFormOnDemand',
uniqueId: 'testuniqueId',
length: 634566, // in milliseconds
stationTitle: 'THEOTV',
programTitle: 'Big Buck Bunny',
episodeTitle: 'Intro',
genreName: 'Animation',
classifyAsAudioStream: false,
customLabels: {
testcustomlabel: 'testcustomvalue'
}
};
const comscoreConnector = new ComscoreConnector(player, comscoreConfig, comscoreMetadata);
```
### 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.
```js
comscoreConnector.updateMetadata(newMetadata);
```
### ComscoreMetadata fields
Based on the `ComscoreMetadata` type, you can tell which fields are mandatory and which aren't. Note that this is purely for the integration to work correctly. Depending on the Comscore solution you are using, different fields are required/optional. The mandatory fields in the `ComscoreMetadata` type are the ones that are mandatory for all three Comscore solutions:
- Video Metrix (V)
- Cross Platform Product Suite (X)
- Cross Media Audience Measurement (C)
| Property | Required | Optional |
| ---------------------------------- | :------: | :------: |
| `mediaType` | All | |
| `uniqueId` | All | |
| `length` | All | |
| `c3?` | V | |
| `c4?` | V | |
| `c6?` | V | |
| `stationTitle` | All | |
| `stationCode?` | | All |
| `networkAffiliate?` | | All |
| `publisherName?` | X C | V |
| `programTitle` | All | |
| `programId?` | | V C |
| `episodeTitle` | All | |
| `episodeId?` | | X C |
| `episodeSeasonNumber?` | X C | |
| `episodeNumber?` | X C | |
| `genreName` | All | |
| `genreId?` | | All |
| `carryTvAdvertisementLoad?` | X | |
| `classifyAsCompleteEpisode?` | X | |
| `dateOfProduction?` | | C |
| `timeOfProduction?` | | C |
| `dateOfTvAiring?` | X C | |
| `timeOfTvAiring?` | | X C |
| `dateOfDigitalAiring?` | X C | |
| `timeOfDigitalAiring?` | | X C |
| `feedType?` | X | |
| `classifyAsAudioStream` | Al | |
| `deliveryMode?` | | All |
| `deliverySubscriptionType?` | | All |
| `deliveryComposition?` | | All |
| `deliveryAdvertisementCapability?` | | All |
| `mediaFormat?` | | All |
| `distributionModel?` | | All |
| `playlistTitle?` | | C |
| `totalSegments?` | | V C |
| `clipUrl?` | | V C |
| `videoDimension?` | | C |
| `customLabels?` | | All |
## Documentation
The integration guidelines from ComScore can be found on their [Unified Digital Measurements page](https://www.comscore.com/Products/Digital/Unified-Digital-Measurement-Enhanced) in the Tagging section.
39 changes: 39 additions & 0 deletions comscore/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "@theoplayer/comscore-connector-web",
"version": "1.0.20",
"description": "A connector implementing Comscore with THEOplayer",
"main": "dist/comscore-connector.umd.js",
"module": "dist/comscore-connector.esm.js",
"types": "dist/types/index.d.ts",
"exports": {
".": {
"types": "./dist/types/index.d.ts",
"import": "./dist/comscore-connector.esm.js",
"require": "./dist/comscore-connector.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 ./.. -o /comscore/test/pages/main.html",
"test": "echo \"No tests yet\""
},
"repository": {
"type": "git",
"url": "git+https://github.com/THEOplayer/web-connectors.git",
"directory": "comscore"
},
"author": "THEO Technologies NV",
"license": "MIT",
"bugs": {
"url": "https://github.com/THEOplayer/web-connectors/issues"
},
"homepage": "https://github.com/THEOplayer/web-connectors#readme",
"peerDependencies": {
"theoplayer": "^7.0.0"
}
}
15 changes: 15 additions & 0 deletions comscore/rollup.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import fs from "node:fs";
import {getSharedBuildConfiguration} from "../tools/build.mjs";


const {version} = JSON.parse(fs.readFileSync("./package.json", "utf8"));

const fileName = "comscore-connector";
const globalName = "THEOplayerComscoreConnector";

const banner = `
/**
* THEOplayer Comscore Web Connector v${version}
*/`.trim();

export default getSharedBuildConfiguration({fileName, globalName, banner});
31 changes: 31 additions & 0 deletions comscore/src/api/ComscoreConfiguration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Ad } from "theoplayer";

export enum ComscoreUserConsent {
denied = "0",
granted = "1",
unknown = ""
}

export enum ComscoreUsagePropertiesAutoUpdateMode {
foregroundOnly = "foregroundOnly",
foregroundAndBackground = "foregroundAndBackground",
disabled = "disabled"
}

export interface ComscoreConfiguration {
/**
* Also known as the c2 value
*/
publisherId: string;
applicationName: string;
userConsent: ComscoreUserConsent;
/**
* Defaults to foregroundOnly if none is specified. If your app has some background experience, use foregroundAndBackground.
*/
usagePropertiesAutoUpdateMode?: ComscoreUsagePropertiesAutoUpdateMode;
skeleton?: any;
adIdProcessor?: (ad: Ad) => string;
debug?: boolean;
}


99 changes: 99 additions & 0 deletions comscore/src/api/ComscoreConnector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { ChromelessPlayer } from 'theoplayer';
import type { ComscoreConfiguration, ComscoreUserConsent } from './ComscoreConfiguration';
import type { ComscoreMetadata } from './ComscoreMetadata';
import { ComscoreStreamingAnalyticsTHEOIntegration } from '../integration/ComscoreStreamingAnalyticsTHEOIntegration';

const USER_CONSENT_LABEL = "cs_ucfr"

export class ComscoreConnector {

private analytics = ns_.analytics
private configuration: ComscoreConfiguration
private streamingAnalyticsIntegration: ComscoreStreamingAnalyticsTHEOIntegration

/**
* Constructor for the THEOplayer Comscore connector
* @param player a THEOplayer instance reference
* @param comscoreConfig configuration object that should at least hold the publisher id, application name and an initial user consent value
* @param comscoreMetadata metadata associated with the SourceDescription that is or will be passed to the THEOplayer instance
* @returns
*/
constructor(player: ChromelessPlayer, comscoreConfig: ComscoreConfiguration, comscoreMetadata: ComscoreMetadata) {
if (typeof ns_ === 'undefined' || typeof this.analytics === 'undefined') {
throw new Error('[COMSCORE] ComScore script missing, cannot init ComScoreAnalytics');
}

this.configuration = comscoreConfig

// Set platform API
if (this.configuration.skeleton) {
this.analytics.PlatformApi.setPlatformAPI(this.analytics.PlatformAPIs.Skeleton, this.configuration.skeleton)
} else {
this.analytics.PlatformApi.setPlatformAPI(this.analytics.PlatformAPIs.html5)
}

// Configure publisher
const publisherConfiguration = new this.analytics.configuration.PublisherConfiguration({
publisherId: comscoreConfig.publisherId,
persistentLabels: {
[USER_CONSENT_LABEL]: comscoreConfig.userConsent || ""
}
})
this.analytics.configuration.addClient(publisherConfiguration)
this.analytics.configuration.setApplicationName(comscoreConfig.applicationName)


// Start application tracking
this.analytics.start()

// Set Streaming Analytics integration
this.streamingAnalyticsIntegration = new ComscoreStreamingAnalyticsTHEOIntegration(player, comscoreConfig, comscoreMetadata);
}

/**
* Sets/updates Comscore metadata on the Comscore video analytics.
* @param metadata object of key value pairs
*/
update(metadata: ComscoreMetadata): void {
this.streamingAnalyticsIntegration.update(metadata);
}

/**
* Update the user consent
* @param consentValue `"1"` indicates consent was granted, `"0"` not granted and `""` unknown.
*/
updateUserConsent(consentValue: ComscoreUserConsent): void {
this.analytics.configuration
.getPublisherConfiguration(this.configuration.publisherId)
.setPersistentLabel(USER_CONSENT_LABEL, consentValue);
this.analytics.notifyHiddenEvent()
}

/**
* Set persistent label on the ComScore PublisherConfiguration
* @param label
* @param value
*/
setPersistentLabel(label: string, value: string): void {
this.analytics.configuration
.getPublisherConfiguration(this.configuration.publisherId)
.setPersistentLabel(label,value);
}

/**
* Set persistent labels on the ComScore PublisherConfiguration
* @param labels object of key value pairs
*/
setPersistentLabels(labels: { [key: string]: string }): void {
this.analytics.configuration
.getPublisherConfiguration(this.configuration.publisherId)
.setPersistentLabels(labels);
}

/**
* Destroy ComScoreStreamingAnalytics and unregister it from player
*/
destroy(): void {
this.streamingAnalyticsIntegration.destroy();
}
}
Loading

0 comments on commit b81e132

Please sign in to comment.