BSDK Step By Step: Difference between revisions
From Engineering Client Portal
NickParrucci (talk | contribs) |
NickParrucci (talk | contribs) |
||
Line 397: | Line 397: | ||
</div> | </div> | ||
== → BSDK DCR Video | == → BSDK DCR Video == | ||
<span class="mw-customtoggle-myDivision1" style="color: cornflowerblue"> Show/hide DCR Video </span> | <span class="mw-customtoggle-myDivision1" style="color: cornflowerblue"> Show/hide DCR Video </span> | ||
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-myDivision1"> | <div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-myDivision1"> | ||
Line 558: | Line 557: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
For this example, we are only going to create content metadata. For information on Ad integration click | For this example, we are only going to create content metadata. For information on Ad integration click [[Digital_Measurement_Metadata|Digital Measurement Metadata]] and see "Ad Metadata" section. | ||
'''Content Metadata Object Properties''' | '''Content Metadata Object Properties''' | ||
Line 571: | Line 570: | ||
|- | |- | ||
| program || Complete program or movie title (no abbreviations or shorthand)<br>''Note: 25 character limit'' || Examples:<br>The Big Bang Theory<br>TheBigBangTheory<br>The Dark Knight<br>TheDarkKnight || Yes || Client | | program || Complete program or movie title (no abbreviations or shorthand)<br>''Note: 25 character limit'' || Examples:<br>The Big Bang Theory<br>TheBigBangTheory<br>The Dark Knight<br>TheDarkKnight || Yes || Client | ||
|- | |||
| title || Episode title with season and episode number (40 character limit)<br>(Formats accepted: S01E03, S1E3, S1 E3) || Examples:<br>The Pants Alternative S03E18<br>The Pants Alternative S3E18<br>The Pants Alternative S3 E18<br>Can also accept:S3E18<br>Not Valid: 318 or 0318 || Yes || Client | |||
|- | |||
| crossId1 || Gracenote TMS ID (If available) should be passed for all telecasted content for clients using the Gracenote solution for proper matching purposes<br>''Note: The TMS ID will be a 14 character string. Normally leading with 2 alpha characerts ('EP', 'MV', 'SH' or 'SP'), followed by 12 numbers'' || The TMS ID will be a 14 character string. Normally with 'EV,' 'EP', 'SH', 'SP', or 'MV' followed by 12 numbers after the initial two letter prefix.<br>Examples:<br>The Giant Morning Show:SH009311820022<br>The Pants Alternative Episode:EP009311820061 || No || Nielsen | |||
|- | |||
| crossId2 || Populated by content distributor to contribute viewing from that distributor to the given content originator || Custom<br>For a full list of acceptable values, please contact your Nielsen representative. || Yes, for distributors || Nielsen | |||
|- | |||
| length || Length of content in seconds<br>''Note: Integers and decimals are acceptable values are acceptable for the length parameter'' || Examples:<br>For standard VOD content - 300 to represent 5 minutes, 1320to represent 22 minutes, etc.<br>If DAI live stream of a discrete program (Live Event/Sporting Event), pass length of content. See example for standard VOD content above.If unknown DAI live steam, pass a value of 0 || Yes || Client | |||
|- | |||
| airdate || Original broadcast or release date for the program:<br>- For USA, date should be EST<br>- Outside USA, date should be local time<br>If not applicable or available, original broadcast or release date for the Program || Acceptable Formats:<br>YYYY-MM-DDTHH:MI:SS<br>YYYY-MM-DDHH:MI:SS<br>YYYY-MM-DDTHH:MI:SS+xx:xx<br>YYYY-MM-DDTHH:MI:SS-xx:xx<br>YYYYMMDDHH:MI:SS<br>YYYYMMDD HH:MI:SS<br>MM-DD-YYYY<br>MM/DD/YYYY<br>YYYYMMDD || Yes || Client | |||
|- | |||
| isfullepisode || Full episode flag to identify differences between long form content || y - full episode<br>n - non full episode(clip,teaser,promo,etc.)<br>Also accept:<br>lf or yes - longform<br>sf or no - shortform || Yes || Nielsen | |||
|- | |||
| adloadtype || Type of ad load:<br>1 Linear - matches TV ad load<br>2 Dyanmic - Dynamic Ad Insertion (DAI) || DCR only uses '2' - DAI || Yes || Nielsen | |||
|- | |||
| segB || One of two custom segments for clients' granular reporting within a brand || Examples:<br>Genre- horror, comedy, etc.<br>Timeslot - primetime, daytime, etc.<br>News type - breakingnews, weather, etc. || No || Client | |||
|- | |||
| segC || One of two custom segments for clients' granular reporting within a brand || Examples:<br>Genre- horror, comedy, etc.<br>Timeslot - primetime, daytime, etc.<br>News type - breakingnews, weather, etc. || No || Client | |||
|} | |} | ||
'''Segment Information''' | |||
Custom segments (segB and segC) can be used to aggregate video and/or static content within a single Brand to receive more granular reports within a brand | |||
Examples regarding usage of segments within SDK: | |||
*All comedy clips and stories for a Brand rolled into a "Comedy" segment | |||
*Genre grouping content by Comedy vs. Drama | |||
*Group related Text + Video content, i.e. for a show that has a lot of - static pages associated with it | |||
*Packaging based on how clients sell inventory | |||
*Grouping related types of content either by genre, category or platform. | |||
Line 581: | Line 605: | ||
</div> | </div> | ||
=== BSDK DCR Video Step 5 - | === BSDK DCR Video Step 5 - Add Video Player === | ||
<span class="mw-customtoggle-myDivisionv6" style="color: cornflowerblue"> Show/hide step 5 </span> | <span class="mw-customtoggle-myDivisionv6" style="color: cornflowerblue"> Show/hide step 5 </span> | ||
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-myDivisionv6"> | <div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-myDivisionv6"> | ||
Add the the video player element to the <body> of your HTML page: | |||
<syntaxhighlight lang="html"> | |||
<video controls src="https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4" | |||
poster="https://peach.blender.org/wp-content/uploads/title_anouncement.jpg?x11217" width="620"> | |||
Sorry, your browser doesn't support embedded videos, | |||
but don't worry, you can <a href="https://archive.org/details/BigBuckBunny_124">download it</a> | |||
and watch it with your favorite video player! | |||
</video> | |||
</syntaxhighlight><br> | |||
If you already have the video the element on the page then proceed to the next step to setup video event listeners. | |||
</div> | </div> | ||
=== BSDK DCR Video Step 6 - | === BSDK DCR Video Step 6 - Set Up Event Listeners === | ||
<span class="mw-customtoggle-myDivisionv7" style="color: cornflowerblue"> Show/hide step 6 </span> | <span class="mw-customtoggle-myDivisionv7" style="color: cornflowerblue"> Show/hide step 6 </span> | ||
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-myDivisionv7"> | <div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-myDivisionv7"> | ||
'''Setup Video Event Listeners''' | |||
In order for the SDK to process player events, you must attach the Browser SDK events to the corresponding player events, e.g. play, pause, and loadmetadata. | |||
'''SDK Events''' | |||
{| class="wikitable" | |||
|- | |||
! Event !! Parameter !! Description | |||
|- | |||
| loadMetadata || content/ad metadata object || Needs to be called at the beginning of each asset | |||
|- | |||
| setPlayheadPosition || Playhead position as integer<br>For VOD: current position in seconds<br>For live content: current Unix timestamp (seconds since Jan-1-1970 UTC)<br>Note: setPlayheadPosition has to be called every second || Pass playhead position every second during playback | |||
|- | |||
| stop || playhead position in seconds || Call when content or ads complete playing and pass playhead position | |||
|- | |||
| end || playhead position in seconds || Call when the current video asset completes playback and pass the playhead position.<br>Example(s): At the end of the content stream, if the user switches to another piece of content, when the browser is refreshed or closed. | |||
|} | |||
'''Query video element'''<br> | |||
First we are going to create a video.js file and setup our event listeners for the video player: | |||
<syntaxhighlight lang="html"> | |||
// Setup Event Listeners w/ SDK Events | |||
// Select the video element | |||
const video = document.querySelector('video'); | |||
</syntaxhighlight> | |||
<br> | |||
'''loadMetadata Event'''<br> | |||
Before SDK can begin crediting, the loadMetadata event must be called at the beginning of each asset by passing the contentMetadata object that was created in the previous step. | |||
<syntaxhighlight lang="html"> | |||
// Load contentMetadata object | |||
video.addEventListener('loadedmetadata', (event) => { | |||
// Call SDK loadmetadata event | |||
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); | |||
}); | |||
</syntaxhighlight> | |||
<br> | |||
'''setPlayheadPosition Event'''<br> | |||
In order to accurately measure the time spent viewing you must pass in the playhead position of the video via the setPlayheadPosition event. | |||
<syntaxhighlight lang="html"> | |||
// Send playhead positions | |||
let playheadPosition = 0; | |||
video.addEventListener('timeupdate', (event) => { | |||
// Perform floor on currentTime property to get current position in seconds | |||
let currTime = Math.floor(video.currentTime); | |||
// Safety check to make sure current time is greater than 0 | |||
if(0 < currTime) { | |||
playheadPosition = currTime; | |||
// Call SDK setplayheadposition event passing in the current playhead | |||
nSdkInstance.ggPM("setPlayheadPosition", playheadPosition); | |||
} | |||
}); | |||
</syntaxhighlight> | |||
<br> | |||
'''stop Event'''<br> | |||
If the player is paused at any time, need to call SDK's stop event and pass the current playhead position | |||
<syntaxhighlight lang="html"> | |||
// Handle Stop | |||
video.addEventListener('pause', (event) => { | |||
nSdkInstance.ggPM("stop", playheadPosition); | |||
}); | |||
</syntaxhighlight> | |||
<br> | |||
'''end Event'''<br> | |||
Once the stream has completed playback, call the end event and pass the ending playhead position. | |||
<syntaxhighlight lang="html"> | |||
// Handle End | |||
video.addEventListener('ended', (event) => { | |||
nSdkInstance.ggPM("end", playheadPosition); | |||
}); | |||
</syntaxhighlight> | |||
<br> | |||
'''Complete video.js file'''<br> | |||
Once complete the video.js file should look like this: | |||
<syntaxhighlight lang="html"> | |||
// Setup Event Listeners w/ SDK Events | |||
// Select the video element | |||
const video = document.querySelector('video'); | |||
// Load contentMetadata object | |||
video.addEventListener('loadedmetadata', (event) => { | |||
// Call SDK loadmetadata event | |||
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); | |||
}); | |||
// Send playhead positions | |||
let playheadPosition = 0; | |||
video.addEventListener('timeupdate', (event) => { | |||
// Perform floor on currentTime property to get current position in seconds | |||
let currTime = Math.floor(video.currentTime); | |||
// Safety check to make sure current time is greater than 0 | |||
if(playheadPosition < currTime) { | |||
playheadPosition = currTime; | |||
// Call SDK setplayheadposition event passing in the current playhead | |||
nSdkInstance.ggPM("setPlayheadPosition", playheadPosition); | |||
} | |||
}); | |||
// Handle Stop | |||
video.addEventListener('pause', (event) => { | |||
nSdkInstance.ggPM("stop", playheadPosition); | |||
}); | |||
// Handle End | |||
video.addEventListener('ended', (event) => { | |||
nSdkInstance.ggPM("end", playheadPosition); | |||
}); | |||
</syntaxhighlight> | |||
<br> | |||
Be sure to add <syntaxhighlight lang="html" inline><script src="video.js"></script></syntaxhighlight> right before the closing <syntaxhighlight lang="html" inline></body></syntaxhighlight> tag in your HTML file! | |||
Line 600: | Line 756: | ||
<span class="mw-customtoggle-myDivisionv8" style="color: cornflowerblue"> Show/hide </span> | <span class="mw-customtoggle-myDivisionv8" style="color: cornflowerblue"> Show/hide </span> | ||
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-myDivisionv8"> | <div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-myDivisionv8"> | ||
Congratulations, you've successfully integrated the Browser SDK on your web page! | |||
<br><br> | |||
[[File:devtoolsbsd1.png|frameless|1000px]] | |||
<br><br> | |||
Final code output: | |||
<br> | |||
<syntaxhighlight lang="html"> | |||
<!DOCTYPE html> | |||
<html lang="en"> | |||
<head> | |||
<meta charset="UTF-8"> | |||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |||
<title>DCR Video Test Page</title> | |||
<script> | |||
// Static Queue Snippet | |||
!function (e, n) { | |||
function t(e) { | |||
return "object" == typeof e ? JSON.parse(JSON.stringify(e)) : e | |||
} | |||
e[n] = e[n] || | |||
{ | |||
nlsQ: function (o, r, c) { | |||
var s = e.document, | |||
a = s.createElement("script"); | |||
a.async = 1, | |||
a.src = ("http:" === e.location.protocol ? "http:" : "https:") + "//cdn-gl.imrworldwide.com/conf/" + o + ".js#name=" + r + "&ns=" + n; | |||
var i = s.getElementsByTagName("script")[0]; | |||
return i.parentNode.insertBefore(a, i), | |||
e[n][r] = e[n][r] || { | |||
g: c || {}, | |||
ggPM: function (o, c, s, a, i) { e[n][r].q = e[n][r].q || []; try { var l = t([o, c, s, a, i]); e[n][r].q.push(l) } catch (e) { console && console.log && console.log("Error: Cannot register event in Nielsen SDK queue.") } }, | |||
trackEvent: function (o) { e[n][r].te = e[n][r].te || []; try { var c = t(o); e[n][r].te.push(c) } catch (e) { console && console.log && console.log("Error: Cannot register event in Nielsen SDK queue.") } } | |||
}, | |||
e[n][r] | |||
} | |||
} | |||
}(window, "NOLBUNDLE"); | |||
// Created SDK Instance | |||
var nSdkInstance = NOLBUNDLE.nlsQ("PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "sdk-video-instance", { | |||
nol_sdkDebug: "debug" | |||
}); | |||
var contentMetadataObject = { | |||
type: 'content', // type of content [required] | |||
assetid: 'VID-123456', // unique ID for each asset [required] | |||
program: 'program name', // name of program [required] | |||
title: 'episode title with season and episode number', // ex: S1E3 [required] | |||
length: 'length in seconds', // length of content [required] | |||
airdate: '20210321 09:00:00', // airdate of broadcast [required] | |||
isfullepisode: 'y', // long form content [required] | |||
adloadtype: '2', // type of ad load (linear/dynamic) [required] | |||
segB: 'custom segment B', // [optional] | |||
segC: 'custom segment C', // [optional] | |||
crossId1: 'Standard Episode ID', // [optional] | |||
crossId2: 'Content Originator' // [optional] | |||
}; | |||
</script> | |||
</head> | |||
<body> | |||
<main> | |||
<h1>DCR Video Sample Page</h1> | |||
<div> | |||
<video controls src="https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4" | |||
poster="https://peach.blender.org/wp-content/uploads/title_anouncement.jpg?x11217" width="620"> | |||
Sorry, your browser doesn't support embedded videos, | |||
but don't worry, you can <a href="https://archive.org/details/BigBuckBunny_124">download it</a> | |||
and watch it with your favorite video player! | |||
</video> | |||
</div> | |||
</main> | |||
<script src="video.js"></script>r | |||
</body> | |||
</html> | |||
</syntaxhighlight> | |||
<br><br> | |||
video.js | |||
<br> | |||
<syntaxhighlight lang="html"> | |||
// Setup Event Listeners w/ SDK Events | |||
// Select the video element | |||
const video = document.querySelector('video'); | |||
// Load contentMetadata object | |||
video.addEventListener('loadedmetadata', (event) => { | |||
// Call SDK loadmetadata event | |||
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); | |||
}); | |||
// Send playhead positions | |||
let playheadPosition = 0; | |||
video.addEventListener('timeupdate', (event) => { | |||
// Perform floor on currentTime property to get current position in seconds | |||
let currTime = Math.floor(video.currentTime); | |||
// Safety check to make sure current time is greater than 0 | |||
if(playheadPosition < currTime) { | |||
playheadPosition = currTime; | |||
// Call SDK setplayheadposition event passing in the current playhead | |||
nSdkInstance.ggPM("setPlayheadPosition", playheadPosition); | |||
} | |||
}); | |||
// Handle Stop | |||
video.addEventListener('pause', (event) => { | |||
nSdkInstance.ggPM("stop", playheadPosition); | |||
}); | |||
// Handle End | |||
video.addEventListener('ended', (event) => { | |||
nSdkInstance.ggPM("end", playheadPosition); | |||
}); | |||
</syntaxhighlight> | |||
<br> | |||
Line 610: | Line 882: | ||
<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-myDivisionv9"> | <div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-myDivisionv9"> | ||
Now that you've integrated the BSDK, what's next? | |||
<br><br> | |||
'''How to debug BSDK integration?''' | |||
In your browser's dev tools menu (Chrome and Edge - press F12) you can inspect the various elements and sources. Here you can see pings being sent by the SDK and various JavaScript sources. Debug-level console logs will be shown if BSDK is debug mode (which you configured during this tutorial). | |||
[[File:devtoolsbsd1.png|frameless|1000px]] | |||
<br><br> | |||
'''Going Live'''<br> | |||
Once the DCR Tracking Code is added, Nielsen will validate the implementation. Following Nielsen testing, users need to make a few updates to the initialization call to ensure that the site is being measured properly. | |||
#App ID: Ensure that correct is used during initialization <br>'PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' | |||
#Debug Logging: Disable logging by deleting {nol_sdkDebug: 'debug'} from initialization call. | |||
<br> | |||
PRODUCTION Initialization Call - Refer to the production initialization call below:<br><br> | |||
<syntaxhighlight lang="html"> | |||
var nSdkInstance = NOLBUNDLE.nlsQ("PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "sdk-video-instance"); | |||
</syntaxhighlight> | |||
</div> | </div> | ||
Line 617: | Line 904: | ||
</div> | </div> | ||
== → BSDK DTVR (coming soon) == | == → BSDK DTVR (coming soon) == |
Revision as of 19:14, 7 June 2023
Provided below are step-by-step quick start guides for implementing Nielsen Browser SDK for DCR Static, DCR Video, and DTVR products. Click each section to get started.
→ BSDK DCR Static
Show/hide DCR Static
BSDK DCR Static Introduction
Show/hide Intro
The Digital Content Ratings (DCR) Static product provides content consumption measurement on client webpages. This measurement includes insight into the total time a user spent on a webpage, how they navigated through the page via links, and many other data points. This tutorial provides the steps to implement the DCR Static product on a standard HTML webpage. It includes:
- Static Queue Snippet: allows for SDK API calls while SDK and configuration file is loading onto page
- SDK Initialization Call: initializes the SDK and static configuration file
- DCR Static Metadata: information about the page(s) being tracked
- staticStart Event: event that starts SDK measurement
By the end of this guide you'll have a webpage that is running Nielsen's Browser SDK in the background:
BSDK DCR Static Step 1 - Obtain AppID
Show/hide step 1
To begin using the Browser SDK (BSDK) you will need to obtain an Application ID (AppId)
Item | Description | Source | |
---|---|---|---|
✅ | App ID (appid) | Unique ID assigned to the player/site and configured by product | Contact your Nielsen TAM |
The appid is a 37 character unique ID assigned to the player/site and configured by product and is required when creating a new instance of the BSDK on the webpage.
Example: PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX
BSDK DCR Static Step 2 - Add Static Queue Snippet
Show/hide step 2
Create HTML page in your preferred editor. In order for SDK to begin tracking, the following code snippet up must be added in a <script> tag to be inserted in <head> tag of the HTML page.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DCR Static Sample Page</title>
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway">
<style>
body,h1,h2,h3,h4,h5 {font-family: "Raleway", sans-serif}
</style>
<script>
// Static Queue Snippet
!function (e, n) {
function t(e) {
return "object" == typeof e ? JSON.parse(JSON.stringify(e)) : e
}
e[n] = e[n] ||
{
nlsQ: function (o, r, c) {
var s = e.document,
a = s.createElement("script");
a.async = 1,
a.src = ("http:" === e.location.protocol ? "http:" : "https:") + "//cdn-gl.imrworldwide.com/conf/" + o + ".js#name=" + r + "&ns=" + n;
var i = s.getElementsByTagName("script")[0];
return i.parentNode.insertBefore(a, i),
e[n][r] = e[n][r] || {
g: c || {},
ggPM: function (o, c, s, a, i) { e[n][r].q = e[n][r].q || []; try { var l = t([o, c, s, a, i]); e[n][r].q.push(l) } catch (e) { console && console.log && console.log("Error: Cannot register event in Nielsen SDK queue.") } },
trackEvent: function (o) { e[n][r].te = e[n][r].te || []; try { var c = t(o); e[n][r].te.push(c) } catch (e) { console && console.log && console.log("Error: Cannot register event in Nielsen SDK queue.") } }
},
e[n][r]
}
}
}(window, "NOLBUNDLE");
</script>
</head>
<body>
</body>
</html>
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.
BSDK DCR Static Step 3 - Make SDK Initialization Call
Show/hide step 3
Create a variable named nSdkInstance and initialize SDK by passing in your App ID into the NOLBUNDLE.nslq() method. Add the following code after the static queue snippet code:
// SDK Initialization call
var nSdkInstance = NOLBUNDLE.nlsQ("PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX", "staticPage", {
nol_sdkDebug: 'debug' // ONLY FOR TESTING! REMOVE BEFORE MOVING TO PRODUCTION
});
When the initialization call is made, a unique static config file, PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX.js, will be loaded on to the page based on the appid and cached by the client-side browser(s). Once the static config file is loaded onto the page, the SDK (nlsSDK600.bundle.min.js) will be fully downloaded and initialized. The initialization call has three parameters:
Parameter | Description | Values |
---|---|---|
App ID (appid) | Unique ID assigned to player/site | PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX |
instanceName | Name of SDK instance | Any string value |
options | Options to be added during initialization | nol_sdkDebug, optout |
NOTE: REMOVE <nol_sdkDebug> OPTION BEFORE GOING INTO PRODUCTION RELEASE
BSDK DCR Static Step 4 - Create DCR Static Metadata Object
Show/hide step 4
Create metadata object which contains information about the static webpage. Add the following code after SDK initialization code:
// DCR Static Metadata Object
var nielsenMetadata = {
type: 'static', // type of content [required]
assetid: 'HHF887465-9486', // unique ID for each article [required]
section: 'HOME', // section of site [required]
segA: '', // custom segment [optional]
segB: '', // custom segment [optional]
segC: '' // custom segment [optional]
};
Metadata Object Properties
Key | Description | Fixed/Dynamic | Value | Required? |
---|---|---|---|---|
type | asset type | fixed | 'static' | Yes |
assetid | Unique ID for each article | dynamic | custom (no Special Characters) | Yes |
section | section of each site (e.g. section value should be first level in page URL: website.com/section). Limit to 25 unique values | dynamic | custom (no Special Characters) | 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 |
Metadata can be passed through key-values using the Nielsen reserved keys. The tracking code includes the Nielsen reserved keys and placeholder values. Pass dynamic metadata for the keys with the value (e.g. section:)
BSDK DCR Static Step 5 - Call ggPM staticStart event
Show/hide step 5
Static Start Event
Make BSDK API call ggPM() passing in the event staticstart as the first parameter and metadata variable as the second parameter. Add the following code after creating your DCR Static metadata object:
nSdkInstance.ggPM('staticstart', staticMetadata);
The content metadata object is passed as a parameter when calling staticstart event.
Static End Event
Call the Browser SDK ggPM() API by passing in the event staticend as the first parameter and metadata variable as the second parameter. In case metadata for another site section has been previously loaded, the staticend API call for that section should be made prior to loading in new metadata (different assetid/section) using a new staticstart API call.
nSdkInstance.ggPM('staticend', staticMetadata);
The content metadata object is passed as a parameter when calling staticend event.
The API call for staticend is not a requirement for all DCR Static integrations, however if client integration is a Single Page Application (SPA) it is imperative that staticend is called prior to the loading of new metadata. This allows the Browser SDK to properly credit the previous section/content being viewed before measuring the new one.
Do not place this call inside beforeunload browser event, because Browser SDK needs some time and resources to deliver data to the cloud.
NOTE: The information on staticend is provided here for reference. The demo site code does not make use of staticend.
BSDK DCR Static Step 6 - Update Page Content
Show/hide step 6
As mentioned in the Create Metadata Object section, the section metadata property correlates to the section of the website the user is currently on. Examples include the home, about, contact, etc. sections often found on webpages. To properly credit the section of the page the user is currently viewing, you must make sure that the section metadata property correctly corresponds with the section or page of the site that the user is currently on. If a user navigates to the contact section of our website (www.example.com/contact) we would have the following in our metadata object:
// DCR Static Metadata Object
var nielsenMetadata = {
type: 'static', // type of content [required]
assetid: 'HHF887465-9486', // unique ID for each article [required]
section: 'CONTACT', // section of site [required]
segA: '', // custom segment [optional]
segB: '', // custom segment [optional]
segC: '' // custom segment [optional]
};
Note: DCR Static is not currently supported in iframe windows.
Keep Going
Show/hide
Congratulations, you've successfully integrated the Browser SDK on your web page!
Final code output:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DCR Static Test Page</title>
<script>
// Static Queue Snippet
!function (e, n) {
function t(e) {
return "object" == typeof e ? JSON.parse(JSON.stringify(e)) : e
}
e[n] = e[n] ||
{
nlsQ: function (o, r, c) {
var s = e.document,
a = s.createElement("script");
a.async = 1,
a.src = ("http:" === e.location.protocol ? "http:" : "https:") + "//cdn-gl.imrworldwide.com/conf/" + o + ".js#name=" + r + "&ns=" + n;
var i = s.getElementsByTagName("script")[0];
return i.parentNode.insertBefore(a, i),
e[n][r] = e[n][r] || {
g: c || {},
ggPM: function (o, c, s, a, i) { e[n][r].q = e[n][r].q || []; try { var l = t([o, c, s, a, i]); e[n][r].q.push(l) } catch (e) { console && console.log && console.log("Error: Cannot register event in Nielsen SDK queue.") } },
trackEvent: function (o) { e[n][r].te = e[n][r].te || []; try { var c = t(o); e[n][r].te.push(c) } catch (e) { console && console.log && console.log("Error: Cannot register event in Nielsen SDK queue.") } }
},
e[n][r]
}
}
}(window, "NOLBUNDLE");
// SDK Initialization [update with your App Id]
var nSdkInstance = NOLBUNDLE.nlsQ("PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX", "staticPage", {
nol_sdkDebug: "debug"
});
// DCR Static Metadata Object
var nielsenMetadata = {
type: 'static', // type of content [required]
assetid: 'HHF887465-9486', // unique ID for each article [required]
section: 'HOME', // section of site [required]
segA: '', // custom segment [optional]
segB: '', // custom segment [optional]
segC: '' // custom segment [optional]
};
// Call staticStart Event
nSdkInstance.ggPM("staticstart", nielsenMetadata);
</script>
</head>
<body class="w3-light-grey">
<div class="w3-content" style="max-width:1400px">
<header class="w3-container w3-center w3-padding-32">
<h1><b>DCR Static Sample Web Page</b></h1>
<p>Sample page with Nielsen's DCR Static Browser SDK integration</p>
</header>
<div class="w3-row">
<div class="w3-col l8 s12">
<div class="w3-card-4 w3-margin w3-white">
<img src="/images/n-logo-aud.avif" alt="Nielsen" style="width: 60%;">
<div class="w3-container">
<h3><b>DCR Static</b></h3>
<h5>Sample Page</h5>
</div>
<div class="w3-container">
<p>Mauris neque quam, fermentum ut nisl vitae, convallis maximus nisl. Sed mattis nunc id lorem euismod placerat. Vivamus porttitor magna enim, ac accumsan tortor cursus at. Phasellus sed ultricies mi non congue ullam corper. Praesent tincidunt sed
tellus ut rutrum. Sed vitae justo condimentum, porta lectus vitae, ultricies congue gravida diam non fringilla.</p>
<div class="w3-row">
<div class="w3-col m8 s12">
<p><button class="w3-button w3-padding-large w3-white w3-border"><b>READ MORE »</b></button></p>
</div>
<div class="w3-col m4 w3-hide-small">
<p><span class="w3-padding-large w3-right"><b>Comments </b> <span class="w3-tag">0</span></span></p>
</div>
</div>
</div>
</div>
<hr>
</div>
<div class="w3-col l4">
<div class="w3-card w3-margin w3-margin-top">
<img src="/images/arrows.jpeg" style="width: 100%; height: 300px;">
<div class="w3-container w3-white">
<h4><b>DCR Static</b></h4>
<p>The Digital Content Ratings (DCR) Static product provides content consumption measurement on client webpages. This measurement includes insight into the total time a user spent on a webpage, how they navigated through the page via links, and many other data points.</p>
</div>
</div><hr>
<hr>
<div class="w3-card w3-margin">
<div class="w3-container w3-padding">
<h4>Tags</h4>
</div>
<div class="w3-container w3-white">
<p><span class="w3-tag w3-black w3-margin-bottom">DCR</span> <span class="w3-tag w3-light-grey w3-small w3-margin-bottom">Static</span> <span class="w3-tag w3-light-grey w3-small w3-margin-bottom">BSDK</span>
<span class="w3-tag w3-light-grey w3-small w3-margin-bottom">Measurement</span> <span class="w3-tag w3-light-grey w3-small w3-margin-bottom">DCR</span>
</p>
</div>
</div>
</div>
</div><br>
</div>
<footer class="w3-container w3-dark-grey w3-padding-32 w3-margin-top">
<button class="w3-button w3-black w3-disabled w3-padding-large w3-margin-bottom">Previous</button>
<button class="w3-button w3-black w3-padding-large w3-margin-bottom">Next »</button>
<p>Powered by <a href="https://www.w3schools.com/w3css/default.asp" target="_blank">w3.css</a></p>
</footer>
</body>
</html>
Next Steps
Show/hide
Now that you've integrated DCR Static for the BSDK, what's next?
How to debug BSDK integration?
In your browser's dev tools menu (Chrome and Edge - press F12) you can inspect the various elements and sources. Here you can see pings being sent by the SDK and various JavaScript sources. Debug-level console logs will be shown if BSDK is debug mode (which you configured during this tutorial).
Going Live
In addition to the basic steps above, before going live developers need to make certain privacy disclosures and allow users to opt out of Nielsen measurement. More details can be found here, along with a more comprehensive reference for implementing DCR Static measurement with BSDK.
Once the DCR Tracking Code is added, Nielsen will validate the implementation. Following Nielsen testing, developers need to make a couple of updates to the initialization call to ensure that the site is being measured properly.
- App ID: Ensure that correct is used during initialization PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
- Debug Logging: Disable logging by deleting {nol_sdkDebug: 'debug'} from initialization call.
PRODUCTION Initialization Call - Refer to the production initialization call below:
var nSdkInstance = NOLBUNDLE.nlsQ("PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "staticPage");
→ BSDK DCR Video
Show/hide DCR Video
BSDK DCR Video Introduction
Show/hide Intro
The Digital Content Ratings (DCR) Video product provides content consumption measurement on client webpages. This measurement includes insight into the total time a user spent watching the tracked content, video player events, and much more. This example provides the steps to implement the DCR Video product using the HTML Video Embed Element. It includes:
- Static Queue Snippet: allows for SDK API calls while SDK and configuration file is loading onto page
- SDK Initialization Call: initializes the SDK and static configuration file
- DCR Video Metadata: information about the player being tracked
- Playhead Event Sequence: event(s) that starts and tracks player measurement
By the end of this guide you'll have a webpage that is running Nielsen's Browser SDK during video playback:
BSDK DCR Video Step 1 - Obtain AppID
Show/hide step 1
To begin using the Browser SDK (BSDK) you will need to obtain an Application ID (AppId)
Item | Description | Source | |
---|---|---|---|
✅ | App ID (appid) | Unique ID assigned to the player/site and configured by product | Contact your Nielsen TAM |
The appid is a 37 character unique ID assigned to the player/site and configured by product and is required when creating a new instance of the BSDK on the webpage.
Example: PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX
BSDK DCR Video Step 2 - Add Static Queue Snippet
Show/hide step 2
Create HTML page in your preferred editor. In order for SDK to begin tracking, the following code snippet up must be added in a <script> tag to be inserted in <head> tag of the HTML page.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DCR Static Sample Page</title>
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Raleway">
<style>
body,h1,h2,h3,h4,h5 {font-family: "Raleway", sans-serif}
</style>
<script>
// Static Queue Snippet
!function (e, n) {
function t(e) {
return "object" == typeof e ? JSON.parse(JSON.stringify(e)) : e
}
e[n] = e[n] ||
{
nlsQ: function (o, r, c) {
var s = e.document,
a = s.createElement("script");
a.async = 1,
a.src = ("http:" === e.location.protocol ? "http:" : "https:") + "//cdn-gl.imrworldwide.com/conf/" + o + ".js#name=" + r + "&ns=" + n;
var i = s.getElementsByTagName("script")[0];
return i.parentNode.insertBefore(a, i),
e[n][r] = e[n][r] || {
g: c || {},
ggPM: function (o, c, s, a, i) { e[n][r].q = e[n][r].q || []; try { var l = t([o, c, s, a, i]); e[n][r].q.push(l) } catch (e) { console && console.log && console.log("Error: Cannot register event in Nielsen SDK queue.") } },
trackEvent: function (o) { e[n][r].te = e[n][r].te || []; try { var c = t(o); e[n][r].te.push(c) } catch (e) { console && console.log && console.log("Error: Cannot register event in Nielsen SDK queue.") } }
},
e[n][r]
}
}
}(window, "NOLBUNDLE");
</script>
</head>
<body>
</body>
</html>
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.
BSDK DCR Video Step 3 - Make SDK Initialization Call
Show/hide step 3
Create a variable named nSdkInstance and initialize SDK by passing in your App ID into the NOLBUNDLE.nslq() method. Add the following code after the static queue snippet code:
// SDK Initialization call
var nSdkInstance = NOLBUNDLE.nlsQ("PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "sdk-video-instance", {
nol_sdkDebug: "debug" // ONLY FOR TESTING! REMOVE BEFORE MOVING TO PRODUCTION
});
When the initialization call is made, a unique static config file, PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX.js, will be loaded on to the page based on the appid and cached by the client-side browser(s). Once the static config file is loaded onto the page, the SDK (nlsSDK600.bundle.min.js) will be fully downloaded and initialized. The initialization call has three parameters:
Parameter | Description | Values |
---|---|---|
App ID (appid) | Unique ID assigned to player/site | PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX |
instanceName | Name of SDK instance | Any string value |
options | Options to be added during initialization | nol_sdkDebug, optout, enableFpid |
NOTE: REMOVE <nol_sdkDebug> OPTION BEFORE GOING INTO PRODUCTION RELEASE
BSDK DCR Video Step 4 - Create DCR Video Content Metadata Object
Show/hide step 4
Create metadata object(s) which contains information about the video. There are two types of asset metadata:
- content: identify video
- ad: identify each ad
// DCR Video Metadata Object
var contentMetadataObject = {
type: 'content', // type of content [required]
assetid: 'VID-123456', // unique ID for each asset [required]
program: 'program name', // name of program [required]
title: 'episode title with season and episode number', // ex: S1E3 [required]
length: 'length in seconds', // length of content [required]
airdate: '20210321 09:00:00', // airdate of broadcast [required]
isfullepisode: 'y', // long form content [required]
adloadtype: '2', // type of ad load (linear/dynamic) [required]
segB: 'custom segment B', // [optional]
segC: 'custom segment C', // [optional]
crossId1: 'Standard Episode ID', // [optional]
crossId2: 'Content Originator' // [optional]
};
For this example, we are only going to create content metadata. For information on Ad integration click Digital Measurement Metadata and see "Ad Metadata" section.
Content Metadata Object Properties
Key | Description | Values | Required? | Provider |
---|---|---|---|---|
type | asset type | content | Yes | Nielsen |
assetid | Unique ID assigned to asset Note: Refrain from using the following special characters Special Characters |
Examples: BBT345a234 CBSs5e234F2021 |
Yes | Client |
program | Complete program or movie title (no abbreviations or shorthand) Note: 25 character limit |
Examples: The Big Bang Theory TheBigBangTheory The Dark Knight TheDarkKnight |
Yes | Client |
title | Episode title with season and episode number (40 character limit) (Formats accepted: S01E03, S1E3, S1 E3) |
Examples: The Pants Alternative S03E18 The Pants Alternative S3E18 The Pants Alternative S3 E18 Can also accept:S3E18 Not Valid: 318 or 0318 |
Yes | Client |
crossId1 | Gracenote TMS ID (If available) should be passed for all telecasted content for clients using the Gracenote solution for proper matching purposes Note: The TMS ID will be a 14 character string. Normally leading with 2 alpha characerts ('EP', 'MV', 'SH' or 'SP'), followed by 12 numbers |
The TMS ID will be a 14 character string. Normally with 'EV,' 'EP', 'SH', 'SP', or 'MV' followed by 12 numbers after the initial two letter prefix. Examples: The Giant Morning Show:SH009311820022 The Pants Alternative Episode:EP009311820061 |
No | Nielsen |
crossId2 | Populated by content distributor to contribute viewing from that distributor to the given content originator | Custom For a full list of acceptable values, please contact your Nielsen representative. |
Yes, for distributors | Nielsen |
length | Length of content in seconds Note: Integers and decimals are acceptable values are acceptable for the length parameter |
Examples: For standard VOD content - 300 to represent 5 minutes, 1320to represent 22 minutes, etc. If DAI live stream of a discrete program (Live Event/Sporting Event), pass length of content. See example for standard VOD content above.If unknown DAI live steam, pass a value of 0 |
Yes | Client |
airdate | Original broadcast or release date for the program: - For USA, date should be EST - Outside USA, date should be local time If not applicable or available, original broadcast or release date for the Program |
Acceptable Formats: YYYY-MM-DDTHH:MI:SS YYYY-MM-DDHH:MI:SS YYYY-MM-DDTHH:MI:SS+xx:xx YYYY-MM-DDTHH:MI:SS-xx:xx YYYYMMDDHH:MI:SS YYYYMMDD HH:MI:SS MM-DD-YYYY MM/DD/YYYY YYYYMMDD |
Yes | Client |
isfullepisode | Full episode flag to identify differences between long form content | y - full episode n - non full episode(clip,teaser,promo,etc.) Also accept: lf or yes - longform sf or no - shortform |
Yes | Nielsen |
adloadtype | Type of ad load: 1 Linear - matches TV ad load 2 Dyanmic - Dynamic Ad Insertion (DAI) |
DCR only uses '2' - DAI | Yes | Nielsen |
segB | One of two custom segments for clients' granular reporting within a brand | Examples: Genre- horror, comedy, etc. Timeslot - primetime, daytime, etc. News type - breakingnews, weather, etc. |
No | Client |
segC | One of two custom segments for clients' granular reporting within a brand | Examples: Genre- horror, comedy, etc. Timeslot - primetime, daytime, etc. News type - breakingnews, weather, etc. |
No | Client |
Segment Information Custom segments (segB and segC) can be used to aggregate video and/or static content within a single Brand to receive more granular reports within a brand Examples regarding usage of segments within SDK:
- All comedy clips and stories for a Brand rolled into a "Comedy" segment
- Genre grouping content by Comedy vs. Drama
- Group related Text + Video content, i.e. for a show that has a lot of - static pages associated with it
- Packaging based on how clients sell inventory
- Grouping related types of content either by genre, category or platform.
BSDK DCR Video Step 5 - Add Video Player
Show/hide step 5
Add the the video player element to the <body> of your HTML page:
<video controls src="https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4"
poster="https://peach.blender.org/wp-content/uploads/title_anouncement.jpg?x11217" width="620">
Sorry, your browser doesn't support embedded videos,
but don't worry, you can <a href="https://archive.org/details/BigBuckBunny_124">download it</a>
and watch it with your favorite video player!
</video>
If you already have the video the element on the page then proceed to the next step to setup video event listeners.
BSDK DCR Video Step 6 - Set Up Event Listeners
Show/hide step 6
Setup Video Event Listeners In order for the SDK to process player events, you must attach the Browser SDK events to the corresponding player events, e.g. play, pause, and loadmetadata.
SDK Events
Event | Parameter | Description |
---|---|---|
loadMetadata | content/ad metadata object | Needs to be called at the beginning of each asset |
setPlayheadPosition | Playhead position as integer For VOD: current position in seconds For live content: current Unix timestamp (seconds since Jan-1-1970 UTC) Note: setPlayheadPosition has to be called every second |
Pass playhead position every second during playback |
stop | playhead position in seconds | Call when content or ads complete playing and pass playhead position |
end | playhead position in seconds | Call when the current video asset completes playback and pass the playhead position. Example(s): At the end of the content stream, if the user switches to another piece of content, when the browser is refreshed or closed. |
Query video element
First we are going to create a video.js file and setup our event listeners for the video player:
// Setup Event Listeners w/ SDK Events
// Select the video element
const video = document.querySelector('video');
loadMetadata Event
Before SDK can begin crediting, the loadMetadata event must be called at the beginning of each asset by passing the contentMetadata object that was created in the previous step.
// Load contentMetadata object
video.addEventListener('loadedmetadata', (event) => {
// Call SDK loadmetadata event
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);
});
setPlayheadPosition Event
In order to accurately measure the time spent viewing you must pass in the playhead position of the video via the setPlayheadPosition event.
// Send playhead positions
let playheadPosition = 0;
video.addEventListener('timeupdate', (event) => {
// Perform floor on currentTime property to get current position in seconds
let currTime = Math.floor(video.currentTime);
// Safety check to make sure current time is greater than 0
if(0 < currTime) {
playheadPosition = currTime;
// Call SDK setplayheadposition event passing in the current playhead
nSdkInstance.ggPM("setPlayheadPosition", playheadPosition);
}
});
stop Event
If the player is paused at any time, need to call SDK's stop event and pass the current playhead position
// Handle Stop
video.addEventListener('pause', (event) => {
nSdkInstance.ggPM("stop", playheadPosition);
});
end Event
Once the stream has completed playback, call the end event and pass the ending playhead position.
// Handle End
video.addEventListener('ended', (event) => {
nSdkInstance.ggPM("end", playheadPosition);
});
Complete video.js file
Once complete the video.js file should look like this:
// Setup Event Listeners w/ SDK Events
// Select the video element
const video = document.querySelector('video');
// Load contentMetadata object
video.addEventListener('loadedmetadata', (event) => {
// Call SDK loadmetadata event
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);
});
// Send playhead positions
let playheadPosition = 0;
video.addEventListener('timeupdate', (event) => {
// Perform floor on currentTime property to get current position in seconds
let currTime = Math.floor(video.currentTime);
// Safety check to make sure current time is greater than 0
if(playheadPosition < currTime) {
playheadPosition = currTime;
// Call SDK setplayheadposition event passing in the current playhead
nSdkInstance.ggPM("setPlayheadPosition", playheadPosition);
}
});
// Handle Stop
video.addEventListener('pause', (event) => {
nSdkInstance.ggPM("stop", playheadPosition);
});
// Handle End
video.addEventListener('ended', (event) => {
nSdkInstance.ggPM("end", playheadPosition);
});
Be sure to add <script src="video.js"></script>
right before the closing </body>
tag in your HTML file!
Keep Going
Show/hide
Congratulations, you've successfully integrated the Browser SDK on your web page!
Final code output:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DCR Video Test Page</title>
<script>
// Static Queue Snippet
!function (e, n) {
function t(e) {
return "object" == typeof e ? JSON.parse(JSON.stringify(e)) : e
}
e[n] = e[n] ||
{
nlsQ: function (o, r, c) {
var s = e.document,
a = s.createElement("script");
a.async = 1,
a.src = ("http:" === e.location.protocol ? "http:" : "https:") + "//cdn-gl.imrworldwide.com/conf/" + o + ".js#name=" + r + "&ns=" + n;
var i = s.getElementsByTagName("script")[0];
return i.parentNode.insertBefore(a, i),
e[n][r] = e[n][r] || {
g: c || {},
ggPM: function (o, c, s, a, i) { e[n][r].q = e[n][r].q || []; try { var l = t([o, c, s, a, i]); e[n][r].q.push(l) } catch (e) { console && console.log && console.log("Error: Cannot register event in Nielsen SDK queue.") } },
trackEvent: function (o) { e[n][r].te = e[n][r].te || []; try { var c = t(o); e[n][r].te.push(c) } catch (e) { console && console.log && console.log("Error: Cannot register event in Nielsen SDK queue.") } }
},
e[n][r]
}
}
}(window, "NOLBUNDLE");
// Created SDK Instance
var nSdkInstance = NOLBUNDLE.nlsQ("PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "sdk-video-instance", {
nol_sdkDebug: "debug"
});
var contentMetadataObject = {
type: 'content', // type of content [required]
assetid: 'VID-123456', // unique ID for each asset [required]
program: 'program name', // name of program [required]
title: 'episode title with season and episode number', // ex: S1E3 [required]
length: 'length in seconds', // length of content [required]
airdate: '20210321 09:00:00', // airdate of broadcast [required]
isfullepisode: 'y', // long form content [required]
adloadtype: '2', // type of ad load (linear/dynamic) [required]
segB: 'custom segment B', // [optional]
segC: 'custom segment C', // [optional]
crossId1: 'Standard Episode ID', // [optional]
crossId2: 'Content Originator' // [optional]
};
</script>
</head>
<body>
<main>
<h1>DCR Video Sample Page</h1>
<div>
<video controls src="https://archive.org/download/BigBuckBunny_124/Content/big_buck_bunny_720p_surround.mp4"
poster="https://peach.blender.org/wp-content/uploads/title_anouncement.jpg?x11217" width="620">
Sorry, your browser doesn't support embedded videos,
but don't worry, you can <a href="https://archive.org/details/BigBuckBunny_124">download it</a>
and watch it with your favorite video player!
</video>
</div>
</main>
<script src="video.js"></script>r
</body>
</html>
video.js
// Setup Event Listeners w/ SDK Events
// Select the video element
const video = document.querySelector('video');
// Load contentMetadata object
video.addEventListener('loadedmetadata', (event) => {
// Call SDK loadmetadata event
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);
});
// Send playhead positions
let playheadPosition = 0;
video.addEventListener('timeupdate', (event) => {
// Perform floor on currentTime property to get current position in seconds
let currTime = Math.floor(video.currentTime);
// Safety check to make sure current time is greater than 0
if(playheadPosition < currTime) {
playheadPosition = currTime;
// Call SDK setplayheadposition event passing in the current playhead
nSdkInstance.ggPM("setPlayheadPosition", playheadPosition);
}
});
// Handle Stop
video.addEventListener('pause', (event) => {
nSdkInstance.ggPM("stop", playheadPosition);
});
// Handle End
video.addEventListener('ended', (event) => {
nSdkInstance.ggPM("end", playheadPosition);
});
Next Steps
Show/hide
Now that you've integrated the BSDK, what's next?
How to debug BSDK integration?
In your browser's dev tools menu (Chrome and Edge - press F12) you can inspect the various elements and sources. Here you can see pings being sent by the SDK and various JavaScript sources. Debug-level console logs will be shown if BSDK is debug mode (which you configured during this tutorial).
Going Live
Once the DCR Tracking Code is added, Nielsen will validate the implementation. Following Nielsen testing, users need to make a few updates to the initialization call to ensure that the site is being measured properly.
- App ID: Ensure that correct is used during initialization
'PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' - Debug Logging: Disable logging by deleting {nol_sdkDebug: 'debug'} from initialization call.
PRODUCTION Initialization Call - Refer to the production initialization call below:
var nSdkInstance = NOLBUNDLE.nlsQ("PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "sdk-video-instance");