Digital Measurement Browser Simplified API
From Engineering Client Portal
Overview
This guide is for the Simplified SDK which has now been replaced by our Global App SDK. As of Sept 21, 2021 the Nielsen Global App SDK was moved to a public repository. Details can be found on the Software Download Page.
This document outlines the features of the Simplified Nielsen SDK, which is available for use within your APP or online video site, for Digital Content Ratings or DTVR measurement. You are only required to execute one of 4 events. Tell the SDK if you want to track 'content', an 'ad', or a 'static' page load. If an event is sent out of sequence, this new API will put it in the correct order for processing. All of the Standard SDK calls can be replaced with one API call, and one dictionary object, where any value could be another complex dictionary object.
Prerequisites
To start using the Simplified API for Browser, you will need an Appid. This is a Unique ID assigned to the player/site and configured by product. If you do not have an AppID , please contact our SDK sales support team. Refer to Digital Measurement Onboarding guide for information on how to get a Nielsen App SDK and appid.
Simplified API
As part of making the SDK more user friendly and reduce the number of app integration touch points, Nielsen has designed a simple interface to pass metadata to the sdk while reducing the number of API calls. The new trackevent()
API has been implemented as a wrapper for the existing SDK and will be responsible for handling new API calls, performing validation, and translation of new API calls to the existing Nielsen App SDK API methods. Applications which are already integrated with the existing SDK API, are unaffected by this new API.
Click here to zoom in on image
Manages the order of metadata (ad vs content and playheads)
Existing API has a number of methods used for reporting player and application state changes to the SDK. Order of calls is important for the SDK in the existing API. In the new enhanced API all these calls will be replaced with one API call that will get one dictionary object with many key-value pairs, where any value could be another complex dictionary object. All the data provided in the existing API in separate calls will be provided in one single call. SDK will analyse the data received in the dictionary object, compare it with the data received previously and generate a sequence of calls for the existing API.
Everything passed via trackevent()
The New API method supports the following event types:
Key | Description |
---|---|
playhead |
It is used to pass content, ad or static metadata, the current playhead value, UNIX timestamp or id3 payload, ott information to the SDK. |
pause |
This event should be passed when the content playback is paused. |
complete |
It is called when session is completed or ends. |
adStop |
Should be called at the end of each ad. This event type is required to handle the case when advertisements could not be distinguished, as its assetId is the same. |
Prerequisites
To get started, an App ID is needed. The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.
'PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'
Configure SDK
There are two steps required for configuring the SDK:
- Add Static Queue Snippet
- Create SDK Instance
Add Static Queue Snippet
Add the following script tag to the website:
<script type = "text/javascript" >
/***************** Static Queue Snippet *********************/
! function(t, n) {
t[n] = t[n] || {
nlsQ: function(e, c, o, r, s, i) {
return s = t.document,
r = s.createElement("script"),
r.async = 1,
r.src = ("http:" === t.location.protocol ? "http:" : "https:") + "//cdn-gl.imrworldwide.com/conf/" +
e + ".js#name=" + c + "&ns=" + n, i = s.getElementsByTagName("script")[0], i.parentNode.insertBefore(r, i),
t[n][c] = t[n][c] || {
g: o || {},
ggPM: function(e, o, r, s, i) {
(t[n][c].q = t[n][c].q || []).push([e, o, r, s, i])
},
trackEvent: function(e) {
(t[n][c].te = t[n][c].te || []).push(e)
}
}, t[n][c]
}
}
}(window, "NOLBUNDLE");
</script>
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.
Create SDK Instance
To initialize the SDK, create an SDK instance by making the initialization call:
Initialization API Call
NOLBUNDLE.nlsQ("<apid>", "<instanceName>",{nol_sdkDebug: "debug", optout: "false"})
When creating an instance, pass the following values: (nol_sdkDebug
and optout
are optional)
Parameter | Description | Values |
---|---|---|
apid | Unique ID assigned to player/site | 'PXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' |
instanceName | Name of SDK instance | "any string value" |
nol_sdkDebug | Enables Nielsen console logging. Only required for testing | "{nol_sdkDebug: "debug"})" |
optout | OptOut global parameter (Optional Parameter) | 1/0 or true/false
|
Example SDK Initialization
When the initialization call is made, a unique static configuration file, <apid>.js, will be downloaded based on the apid and will be cached on the user’s browser.
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK600.bundle.min.js”.
More information on OptOut Parameter under Privacy and Opt-Out.
Example SDK Configuration
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:
<script type = "text/javascript" >
/***************** Static Queue Snippet *********************/
! function(t, n) {
t[n] = t[n] || {
nlsQ: function(e, c, o, r, s, i) {
return s = t.document,
r = s.createElement("script"),
r.async = 1,
r.src = ("http:" === t.location.protocol ? "http:" : "https:") + "//cdn-gl.imrworldwide.com/conf/" + e + ".js#name=" + c + "&ns=" + n, i = s.getElementsByTagName("script")[0], i.parentNode.insertBefore(r, i),
t[n][c] = t[n][c] || {
g: o || {},
ggPM: function(e, o, r, s, i) {
(t[n][c].q = t[n][c].q || []).push([e, o, r, s, i])
},
trackEvent: function(e) {
(t[n][c].te = t[n][c].te || []).push(e)
}
}, t[n][c]
}
}
}(window, "NOLBUNDLE");
// Created SDK Instance
var nSdkInstance = NOLBUNDLE.nlsQ("XXXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX", "nlsnInstance", {
nol_sdkDebug: "debug",
optout: "false"
});
</script>
Simplified API Syntax
The existing API has a number of methods used for reporting player and application state changes to the SDK. The order of calls is important for the SDK in the existing API. In the new simplified API, all these calls will be replaced with one API call that will get one dictionary object with many key-value pairs, where any value could be another complex dictionary object. All the data provided in the older API in separate calls will be provided in one single call.
Main API call for the new NielsenEventTracker API:
nSdkInstance.trackEvent({metadata})
Handling JSON Metadata
Parameter “data” is a JSON object with many key-value pairs that holds all information required by SDK.
Format of input object is the following:
{
"event": <event identifier>,
"type": <type of metadata>,
"metadata":{
"content": <content metadata object>,
"ad": <ad metadata object>,
"static": <static metadata object>
},
"playheadPosition":<playhead value | UNIX timestamp (seconds since Jan-1-1970 UTC) >,
"id3Data": <id3 payload>,
}
Event Types
The New API method supports the following event types:
Key | Description |
---|---|
playhead |
It is used to pass content, ad or static metadata, the current playhead value, Unix timestamp or id3 payload, ott information to the SDK. |
pause |
This event should be used when
content playback is paused. |
complete |
It is called when session is completed or ends. |
adStop |
Should be called at the end of each ad. This event type is required to handle the case when advertisements could not be distinguished, as its assetId is the same. |
DCR and DTVR require various levels of data. Please select the TAB of the product you are interested in reviewing.
DCR
Digital Content Ratings
Parameter | Description | Supported values | Example |
---|---|---|---|
event | Event identifier |
|
"event":"playhead"
|
type | Determines the metadata object
that should be used for crediting. |
|
"type":"content"
|
metadata | Object that holds metadata values of specific types Detailed in tables below |
Object
|
"metadata":{
"content": <content metadata object>,
"ad": <ad metadata object>,
"static": <static metadata object>
},
|
playheadPosition | Playhead value in seconds or Unix timestamp | String
|
Position value is Unix timestamp:
Position value is playhead:
|
Content Metadata
Content metadata sent for every playheadposition update.
Keys | Description | Example | Required |
---|---|---|---|
assetid | unique ID assigned to asset | custom | Yes |
length | length of content in seconds | seconds (0 for live stream) |
Yes |
program | name of program (100 character limit) | custom | Yes |
title | name of program (100 character limit) | custom | Yes |
type | 'content', 'ad', 'static' |
'content' |
Yes |
airdate | the airdate in the linear TV ++ | YYYYMMDD HH24:MI:SS | Yes |
isfullepisode | full episode flag | "y" - full episode, "n" - non full episode |
Yes |
crossId1 | Gracenote ID or Enterprise ID | custom | Yes |
crossId2 | content originator or network (only required for distributors) | custom | |
adloadtype | linear vs dynamic ad model | 1=Linear
2=Dynamic Ads |
custom |
++ Acceptable Air Date Formats:
YYYYMMDD HH24:MI:SS
YYYYMMDDHH24MISS
YYYY-MM-DDTHH:MI:SS
YYYY-MM-DDHH:MI:SS
YYYYMMDDHH:MI:SS
MM-DD-YYYY
YYYYMMDD HH:MI:SS
For USA all times should be EST, for all other countries Local Time.
Below is a sample event for DCR. If no ad or static values, these can be left as blank/null.
{
"event": "playhead",
"type": "content",
"metadata": {
"content":{
"assetid":"B66473",
"length":"3600",
"program":"MyProgram",
"title":"S2,E3",
"type":"content",
"airdate":"20180120 10:00:00",
"isfullepisode":"y",
"crossId1":"Standard Episode ID",
"crossId2" :"Content Originator",
"adloadtype":"2"},
"ad": {},
"static": {}
},
"playheadPosition": "",
}
DTVR
Digital TV Ratings info
Parameter | Description | Supported values | Example |
---|---|---|---|
event | Event identifier |
|
"event":"playhead"
|
type | Determines the metadata object that should be used for crediting. |
|
"type":"content"
|
adModel | linear vs dynamic ad model | 1=Linear
2=Dynamic Ads |
custom |
channelName | Any string representing the.channel/stream | Object
|
custom |
playheadPosition | Playhead value in seconds or Unix timestamp | String
|
Position value is Unix timestamp:
Position value is playhead:
|
id3Data | Nielsen ID3 payload string | Object
|
|
Below is a sample event for DTVR. If no ad or static values, these can be left as blank/null.
{
"event": "playhead",
"type": "content",
"metadata": {
"content":{
"adModel":"1",
"channelname":"channel1"
},
"ad": {},
"static": {}
},
"playheadPosition": "",
"id3Data": "www.nielsen.com/065H2g6E7ZyQ5UdmMAbbpg==/_
EMc37zfVgq_8KB7baUYfg==/ADQCAmgV1Xyvnynyg60kZO_Ejkcn
2KLSrTzyJpZZ-QeRn8GpMGTWI7-HrEKzghxyzCyBEoIDv2kA2g1Q
JmeYOl5GnwfrLDVK2bNLTbQxr1z9VBfxahBcQP5tqbjhyMzdVqrMK
uvvJO1jhtSXa9AroChb11ZUnG1WVJx2O4M=/33648/22847/00"
}
DCR & DTVR
Applies to DCR and DTVR
Parameter | Description | Supported values | Example |
---|---|---|---|
event | Event identifier |
|
"event":"playhead"
|
type | Determines the metadata object that should be used for crediting. |
|
"type":"content"
|
metadata | Object that holds metadata values of specific types Detailed in tables below |
Object
|
"metadata":{
"content": <content metadata object>,
"ad": <ad metadata object>,
"static": <static metadata object>
},
|
playheadPosition | Playhead value in seconds or Unix timestamp | String
|
Position value is Unix timestamp:
Position value is playhead:
|
id3Data | Nielsen ID3 payload string | Object
|
|
ottData | Object that holds ott information | Object
|
ottData:{
ottStatus:1,
ottType:casting,
ottDevice:chromecast,
ottDeviceName:Google ChromeCast,
ottDeviceID:1234,
ottDeviceModel:ChromeCast,
ottDeviceVersion:1.0.0
}
|
Content Metadata
Content metadata sent for every playheadposition update.
Keys | Description | Example | Required |
---|---|---|---|
assetid | unique asset ID for DCR; can be set to "0" for DTVR | EP732481 |
Yes |
length | length of content in seconds | seconds (0 for live stream) |
Yes |
type | 'content', 'ad', 'static' |
'content' |
Yes |
adModel | linear vs dynamic ad model | 1=Linear
2=Dynamic Ads |
custom |
adloadtype | DCR Ad Model | 1=Linear
2=Dynamic Ads |
custom |
++ Acceptable Air Date Formats:
YYYYMMDD HH24:MI:SS
YYYYMMDDHH24MISS
YYYY-MM-DDTHH:MI:SS
YYYY-MM-DDHH:MI:SS
YYYYMMDDHH:MI:SS
MM-DD-YYYY
YYYYMMDD HH:MI:SS
Below is a sample event for DCR/DTVR joint integration. If no ad or static values, these can be left as blank/null.
{
"event": "playhead",
"type": "content",
"metadata": {
"content":{
"type":"content",
"assetid":"0",
"length":"0",
"adModel":"1",
"adloadtype":"1"},
"ad": {},
"static": {}
},
"playheadPosition": "",
"id3Data": "www.nielsen.com/065H2g6E7ZyQ5UdmMAbbpg==/_
EMc37zfVgq_8KB7baUYfg==/ADQCAmgV1Xyvnynyg60kZO_Ejkcn
2KLSrTzyJpZZ-QeRn8GpMGTWI7-HrEKzghxyzCyBEoIDv2kA2g1Q
JmeYOl5GnwfrLDVK2bNLTbQxr1z9VBfxahBcQP5tqbjhyMzdVqrMK
uvvJO1jhtSXa9AroChb11ZUnG1WVJx2O4M=/33648/22847/00"
}
Ad Metadata
The ad metadata (if applicable) should be passed for each individual ad, if ads are available during or before the stream begins.
Keys | Description | Values | Example |
---|---|---|---|
assetid | unique ID assigned to ad | custom (no Special Characters) |
'AD1234'
|
title | unique name assigned to ad | custom | 'ADtitle'
|
adldx | Ad Index (*See Note below*) | custom | "66478364"
|
type | type of ad | 'preroll', 'midroll', or 'postroll' | 'preroll'
|
length | length of ad | In Seconds | '20'
|
Ad Metadata Sample
{
"ad": {
"assetid":"AD12345",
"title":"ADTestTitle",
"adldx":"1",
"type":"preroll",
"length":"20"
},
}
Managing Ads
If there is an Ad block within the playing content (such as a midroll) you need to:
- Reset the playhead position to 0 for each ad.
- Call the adStop event at the end of each ad or increment the adldx
The Simplified API will can automatically detect the change from ad to content, or even ad to ad if the assetID changes; however, there could be situations where the same ad is played back to back. You can either increment/change the adldx value, and/or call adStop at the end of each Ad.
Sometimes it is not possible for integrators to provide different assetId value for individual ads in a sequence of ads. Taking this into account the Nielsen Simplified API will support a new parameter for ad metadata: adIdx. This parameter is just an index of an individual ad in a sequence of ads. Once the next ad is started the adIdx parameter should be changed and provided as part of ad metadata.
// Example of passing both values
self.data.updateValue("adStop", forKey: "event")
self.data.updateValue("223", forKey: "adldx")
self.nielsenEventTracker.trackEvent(data)
Static Metadata
The values passed through the Nielsen keys will determine the breakouts that are seen in reporting. The custom segments (A, B & C) will roll into the sub-brand. To not use custom segments A, B and C, do not pass any value in these keys.
Key | Description | Data Type | Value | Required? |
---|---|---|---|---|
assetid | Unique ID for each article | dynamic | custom (no Special Characters) |
Yes |
section | Section of each site which is limited to 25 unique values (e.g. section value should be first level in page URL: website.com/section). |
dynamic | custom | Yes |
segA | custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) |
dynamic | custom | No |
segB | custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) |
dynamic | custom | No |
segC | custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) |
dynamic | custom | No |
Aggregation Limits There are limits on the number of unique values that can be aggregated on in reporting. The specific limitations by key are:
Key | Aggregation Limit |
---|---|
section | maximum of 25 unique values (section <= 25) |
segA | Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25) |
segB | Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25) |
segC | Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25) |
Static Metadata Sample
// Sample input Object for static metadata
// Since only recording static data, playheadposition = ""
{
"metadata": {
"content": {},
"ad": {},
"static": {
"type":"static",
"assetid":"Static1",
"section":"Page",
"segA":"S07E04:NBC",
"segB":"teams",
"segC":"Atlanta",
"crossId1":"Reference"
}
},
"event": "playhead",
"type": "static",
"playheadPosition": "",
}
Json Examples
Addtional JSON input object examples.
Privacy and Opt-Out
There are two primary methods for implementing user Opt-out preferences:
- User Opt Out - Provide a link to the Nielsen Privacy Policy page when a User can make their selection
- Initialization Opt Out - Global OptOut Parameter
User Opt Out
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the User Opt-Out option, include the following two items in your privacy policy.
- A notice that the player (or page in relation to static measurement) includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).
- A link to the Nielsen Digital Measurement Privacy Policy at https://www.nielsen.com/digitalprivacy
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.
- Once users have opted out via this link, their browser cookies will contain the value TOTAL_OPTOUT. This will prevent a redirect to our data provider from occurring
- Users can opt back in via this link. When a user selects that link, their opt-out cookie will be deleted and they will be able to be measured moving forward.
The following paragraph is a template for a Privacy Statement.
The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://www.nielsen.com/digitalprivacy
User Opt Back In
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.
Initialization Opt Out
The BSDK600 now supports the ability to optout on initialization of the SDK by allowing an optout global parameter to be passed. This optout will be maintained through the session of the SDK instance. Specifications and limitations are specified below.
Type | Supported Values | Notes | Optout |
---|---|---|---|
optout | True, Yes, or 1 | Case is insensitive and can be string or bool
Example: nlsQ("XXXXXXXX-BH45-JKY6-BKH7-67GJKY68GJK7", "myInstance", { optout: true}); |
Ping parameter will set uoo=true. |
optout | False, No, or 0 | Case is insensitive and can be string or bool
Example: nlsQ("XXXXXXXX-BH45-JKY6-BKH7-67GJKY68GJK7", "myInstance", { optout: false}); |
Ping parameter will set uoo to blank. |
Example of using OptOut
var nSdkInstance = NOLBUNDLE.nlsQ("XXXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX", "nlsnInstance", {
nol_sdkDebug: "debug",
optout: "true"
});
Opt Out Overview
Browser Cookie | uoo value in session ping | Final Optout Status |
---|---|---|
Default Value | no uoo value or uoo=0 | Not Opted Out |
Default Value | uoo=1 | Opted Out |
TOTAL_OPTOUT | uoo=0 | Opted Out |
TOTAL_OPTOUT | uoo=1 | Opted Out |
Going Live
After the integration has been certified, users will need to make a couple of updates to the initialization call to ensure that player will be measured properly. Disable debug logging by deleting {nol_sdkDebug: 'DEBUG'} from initialization call. Example Production Initialization Call
var nSdkInstance = NOLBUNDLE.nlsQ("XXXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX", "nlsnInstance", { optout: "false"});
Sample Code
This code is for example purposes only to demonstrate a very simple video implementation, with a single preroll and single content block.
<script >
// Setup videojs sample player
var nielsenid = document.getElementById("my-sdkplayer");
var coolPlayer = videojs('my-sdkplayer', {
controls: true,
autoplay: true,
preload: 'auto',
});
var prevPos = null;
coolPlayer.preroll({
src: {
src: "assets/CleaningCrew.mp4",
type: "video/mp4"
},
href: "http://videojs.com",
adsOptions: {
debug: true
}
});
videojs('my-sdkplayer').ready(function() {
// EXAMPLE: Start playing the video.
coolPlayer.play();
var obj = {
event: 'playhead', // playhead,pause,complete,adstop
type: 'content',
playheadPosition: '0',
metadata: {
content: {
type: 'content',
assetid: 'VID98-2B88',
program: 'Put a programname here ',
title: 'S01E02',
length: '180',
airdate: '20190101 10:01:00',
isfullepisode: 'y',
crossId1: 'Standard Episode ID',
crossID2: 'Content Originator',
adloadtype: '2'
},
ad: {},
static: {}
}
};
coolPlayer.on('timeupdate', function() {
var getcurrentTime = coolPlayer.currentTime();
var intPlayedTime = parseInt(getcurrentTime, 10);
if (intPlayedTime > 0 && intPlayedTime !== prevPos && !coolPlayer.scrubbing()) {
// check for playhead change so it's only called once per second
console.log('PLAYHEAD EVENT **************************************************************');
console.log(Math.round(getcurrentTime));
obj.event = 'playhead';
obj.type = 'content';
obj.metadata.ad = {};
prevPos = intPlayedTime;
obj.playheadPosition = Math.round(getcurrentTime);
nSdkInstance.trackEvent(obj);
}
});
this.on('adstart', function() {
console.log('ADSTART EVENT **************************************************************');
obj.type = 'ad';
obj.metadata.ad = {
type: 'preroll',
assetid: 'AD9455',
adldx: '1',
program: 'Cant Skip Campaign',
title: 'Cleaning Crew',
length: '36',
};
nSdkInstance.trackEvent(obj);
});
this.on('contentresumed', function() {
console.log('CONTENT RESUMED EVENT **************************************************************');
obj.type = 'content';
obj.event = 'playhead';
obj.metadata.ad = {};
nSdkInstance.trackEvent(obj);
});
this.on('pause', function() {
console.log('PAUSE EVENT **************************************************************');
obj.event = 'pause';
obj.playheadPosition = Math.round(coolPlayer.currentTime());
nSdkInstance.trackEvent(obj);
});
this.on('adtimeupdate', function() {
var getcurrentTime = coolPlayer.currentTime();
var intPlayedTime = parseInt(getcurrentTime, 10);
if (intPlayedTime > 0 && intPlayedTime !== prevPos) {
// check for playhead change so it's only called once per second
console.log('AD PLAYHEAD EVENT **************************************************************');
console.log(Math.round(getcurrentTime));
prevPos = intPlayedTime;
obj.playheadPosition = Math.round(getcurrentTime);
nSdkInstance.trackEvent(obj);
};
});
this.on('adend', function() {
console.log('AD STOP EVENT **************************************************************');
obj.event = 'adstop';
nSdkInstance.trackEvent(obj);
});
this.on('ended', function() {
console.log('COMPLETE EVENT **************************************************************');
obj.event = 'complete';
nSdkInstance.trackEvent(obj);
});
});
</script>