Difference between revisions of "DCR Denmark Video Cloud API"

From Engineering Client Portal

(Example Request)
(11 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}
+
{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International DCR}}  {{CurrentBreadcrumb}}
 
[[Category:Digital]]
 
[[Category:Digital]]
  
 +
= DCR Integration Utilizing Cloud API =
 
This guide shows you how to integrate the Nielsen Cloud API to enable Digital Content Ratings (DCR), and fuel other measurement products on your over-the-top (OTT) Apps.
 
This guide shows you how to integrate the Nielsen Cloud API to enable Digital Content Ratings (DCR), and fuel other measurement products on your over-the-top (OTT) Apps.
 
+
__TOC__
 
==Prerequisites==
 
==Prerequisites==
To get started, you will need a Nielsen App ID. The App ID is a unique ID assigned to your app. This will be provided to you upon starting the integration.
+
To get started, you will need a Nielsen App ID. The App ID is a unique ID assigned to your app. This will be provided to you by your assigned Technical Account Manager upon starting the integration.
  
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight>
+
{| class="wikitable"
 +
|-
 +
! style="width: 15%;" | Item
 +
! Description
 +
! Source
 +
|-style="background-color:#d0f6f8;"
 +
|| '''App ID (appid)''' || Unique ID assigned to the player/site and configured by product. || Provided by Nielsen
 +
|}
  
 
==Integration==
 
==Integration==
 
We will cover the steps for constructing the Cloud API Calls.
 
We will cover the steps for constructing the Cloud API Calls.
 
===Request Overview===
 
  
 
====URL Structure====
 
====URL Structure====
Line 31: Line 37:
 
There are endpoints for testing and production:
 
There are endpoints for testing and production:
  
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code>
+
*Testing: <code>https://sc-eucert.nmrodam.com/nmapi/v2/</code>
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code>
+
*Production: <code>https://capi-dmk.nmrodam.com/nmapi/v2/</code>
  
 
During testing, all calls should be pointed to the testing endpoint. We will review the update to the production endpoint during the Go Live section of this guide.
 
During testing, all calls should be pointed to the testing endpoint. We will review the update to the production endpoint during the Go Live section of this guide.
Line 40: Line 46:
  
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=
+
https://sc-eucert.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=
 
{
 
{
 
   "devInfo": [deviceInfo],
 
   "devInfo": [deviceInfo],
Line 50: Line 56:
 
   "position": [playhead_position],
 
   "position": [playhead_position],
 
   "type": [asset type],
 
   "type": [asset type],
   "utc": [Unix time in ms]
+
   "utc": [Unix time in ms],
 +
  "sessid": [unique view session ID for each video play]
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Create Session ID===
+
===Create Session ID and send EMM Ping===
A unique Session ID must be created upon app launch and provided in the URL. This will allow measurement to occur for the entire duration that a user is within the app.
+
 
 +
====Create Session ID====
 +
 
 +
A unique Session ID <code>[sessionID]</code> must be created upon app launch and provided in the URL. This will allow measurement to occur for the entire duration that a user is within the app.
  
A Session ID needs to be completely unique so it is recommended to use a version 4 UUID or another method of your choosing to guarantee there are no repeats.
+
A Session ID needs to be completely unique so it is recommended to use a version 4 UUID or another method of your choosing to guarantee there are no repeats, also see  [[#Review the Reference Implementation for VoD and Live Streams|Reference Implementation for VoD and Live Streams]] for your reference and use.
  
 
Upon exiting the app, the session will need to be terminated using the delete event. Sessions will automatically expire after 30 minutes of cloud inactivity.
 
Upon exiting the app, the session will need to be terminated using the delete event. Sessions will automatically expire after 30 minutes of cloud inactivity.
 +
 +
====Send EMM Ping====
 +
An EMM Ping must be sent using the created unique Session ID <code>[sessionID]</code> upon start of the first stream playback.
 +
<syntaxhighlight lang="javascript">
 +
https://[sessionID].uaid.nmrodam.com/
 +
</syntaxhighlight>
 +
Also see  [[#Review the Reference Implementation for VoD and Live Streams|Reference Implementation for VoD and Live Streams]] for your reference.
 +
 +
===Create First Party ID===
 +
* An First Party ID  <code>[fpid]</code> must be created and stored on the device. It is re-used until expiration date or if the user has deleted it on from the device storage.
 +
The default expiration date should be set to the equivalent of 180 days.
 +
* Additionally the Creation Time <code>[fpcrtm]</code> of the First Party ID should be stored as well. The same value should be used as long as the First Party ID is available on the device.
 +
 +
===Create View Session ID for each Video Start===
 +
An View Session ID <code>[sessid]</code> must be created upon start of each stream playback, sessid is unique per video play.
  
 
===Define URL Structure===
 
===Define URL Structure===
 
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.
 
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.
  
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight>
+
<syntaxhighlight lang="javascript">https://sc-eucert.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight>
  
 
===Configure Payload===
 
===Configure Payload===
Line 87: Line 112:
 
         "apn": "AppName",
 
         "apn": "AppName",
 
         "apv": "1.0",
 
         "apv": "1.0",
         "uoo": "false"
+
         "fpid": "First Party ID",
 +
        "fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"
 
     },
 
     },
 
      
 
      
Line 99: Line 125:
 
             "title": "Episode Title S3 - EP1", // episode name
 
             "title": "Episode Title S3 - EP1", // episode name
 
             "length": "1800", // content duration in seconds
 
             "length": "1800", // content duration in seconds
            "segB": "Custom Segment B", // custom segment
 
            "segC": "Custom Segment C", // custom segment
 
            "crossId1": "Standard Episode ID", // episode ID
 
            "crossId2": "Content Originator ID", // content orginator (required for distributors)
 
 
             "airdate": "20161013 20:00:00", // airdate
 
             "airdate": "20161013 20:00:00", // airdate
             "adloadtype": "2" //ad load flag
+
             "adloadtype": "2", //ad load flag
             "hasAds": "1", // content contains ads = 1 / no ads = 0
+
             "subbrand": "c05", // channel ID or subrand provided by Nielsen
             "progen": "CV" // program genre abbreviation
+
            "stationId": "TESTXXYYSSWWLL",
 +
            "islivestn": "y",
 +
             "pbstarttm": "1631098029"
 
         },
 
         },
 
         "ad": {
 
         "ad": {
Line 118: Line 142:
 
     "position": "300", // position in seconds
 
     "position": "300", // position in seconds
 
     "type": "content", //"content" or "ad"
 
     "type": "content", //"content" or "ad"
     "utc": "1456448742000" //unix timestamp in milliseconds  
+
     "utc": "1456448742000", //unix timestamp in milliseconds  
 +
    "sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 129: Line 154:
 
! Keys !! Description !! Values !! Required
 
! Keys !! Description !! Values !! Required
 
|-
 
|-
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || Yes
+
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom ||
 
|-
 
|-
| apn || app name || custom || Yes
+
| apn || app name || custom ||
 
|-
 
|-
| apv || app build version || custom || Yes
+
| apv || app build version || custom ||
|-
+
|-style="background-color:#d0f6f8;"
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes
+
| fpid || First Party ID || custom ||
 +
|-style="background-color:#d0f6f8;"
 +
| fpcrtm || Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds) || custom ||
 
|-
 
|-
 
|}
 
|}
Line 146: Line 173:
 
   "apn": "AppName",
 
   "apn": "AppName",
 
   "apv": "1.0",
 
   "apv": "1.0",
   "uoo": "false"
+
   "fpid": "First Party ID",
 +
  "fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"
 
},
 
},
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 157: Line 185:
 
===== Content Metadata =====
 
===== Content Metadata =====
 
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.
 
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.
 +
 +
<br/>
 +
<blockquote> program and title metadata values should be passed to SDK as UTF-8 strings. </blockquote>
  
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! Keys !! Description !! Values !! Required
+
! Keys !! Description !! Values !! Required
|-
 
| type || type of asset || <code>"content"</code> || Yes
 
 
|-
 
|-
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes
+
| type || type of asset || "content" for main content ||
 
|-
 
|-
| program ||name of program (25 character limit) || custom || Yes
+
| assetid || unique ID assigned to asset || custom<br>(no [[Special Characters]]) ||
 
|-
 
|-
| title ||name of program (25 character limit) || custom || Yes
+
| program || name of program || custom ||
 
|-
 
|-
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes
+
| title || episode name || custom ||
 
|-
 
|-
| segB || custom segment B || custom || No
+
| length || length of content in seconds || Length of content in seconds (86400 seconds for live stream (24/7). For Event-Live streams planned length. For VoD video length)||
 
|-
 
|-
| segC || custom segment C || custom || No
+
| airdate || the original date (local time with hh:mm:ss as 24h time stamp) content became available. This date does not change if the content is rebroadcasted on linear TV. || YYYYMMDD HH:MI:SS (if not known set it to eg. "19700101 00:00:00") ||
 
|-
 
|-
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes
+
| isfullepisode || full episode flag ||
 +
* "y" full episode (full content for a program)
 +
* "n" non full episode (only one part of the entire content for a program , i.e. preview, sub-episodes)
 +
||
 +
 
|-
 
|-
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes
+
|adloadtype || type of Ad load
 +
||
 +
:
 +
* "1" Linear - matches TV ad load
 +
* "2" Dynamic - Dynamic Ad Insertion (DAI)
 +
||
 +
 +
|-style="background-color:#d0f6f8;"
 +
|stationId || Unique Gracenote Station ID generated by Nielsen that uniquely identifies a live channel
 +
||
 +
provided by Nielsen
 +
||
 +
 +
|-style="background-color:#d0f6f8;"
 +
|islivestn || Indicates if a stream is playing on a live channel
 +
||
 +
:
 +
* "y" playing on a live channel
 +
* "n" otherwise i.e. VoD
 +
||
 +
 +
|-style="background-color:#d0f6f8;"
 +
|pbstarttm || Playback Start Time (UTC): Unix timestamp in seconds matching the broadcast time for Content and Ad when a user starts and joins a live stream (seconds since Jan-1-1970 UTC)
 +
||
 +
i.e. "1631098029" for live stream and ""(empty string) for a VoD.
 +
||
 +
 
|-
 
|-
| crossId1 || standard episode ID || custom || Yes
+
| subbrand || vcid/sub-brand/Channel  ID – value is automatically populated through provided AppID. In order to override the sub-brand configured to the App ID, value can be passed here (e.g. multiple sub-brands/Channels in the App)
|-
+
||
| crossId2 || content originator (only required for distributors) || Nielsen || No
+
provided by Nielsen  
|-
+
||
| adloadtype || type of ad load:
+
<code>"1"</code> Linear – matches TV ad load
+
|}
  
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)
 
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes
 
|-
 
| hasAds || ads indicator
 
<code>"1"</code>: ads included
 
 
<code>"0"</code>: ads not included
 
|| <code>"1"</code> or <code>"0"</code> || Yes
 
|-
 
| subbrand || sub brand override || Nielsen || No
 
|-
 
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes
 
|}
 
  
  
Line 205: Line 251:
 
<syntaxhighlight lang='json'>// create content object
 
<syntaxhighlight lang='json'>// create content object
 
"content": {
 
"content": {
    "type": "content",
+
  "type": "content",
    "assetid": "VIDEO-ID123",
+
  "assetid": "unique_content_id",
    "isfullepisode": "y",
+
  "program": "program name",
    "program": "Program Name",
+
  "title": "episode title",
    "title": "Episode Title S3 - EP1",
+
  "length": "length in seconds",
    "length": "1800",
+
  "airdate": "20200713 10:22:00",
    "segB": "Custom Segment B",
+
  "isfullepisode": "y",
    "segC": "Custom Segment C",
+
  "adloadtype": "2",
    "crossId1": "Standard Episode ID",
+
  "subbrand": "c05",
    "crossId2": "Content Originator ID",
+
  "stationId": "TESTXXYYSSWWLL",
    "airdate": "20161013 20:00:00",
+
  "islivestn": "y",
    "adloadtype": "2",
+
  "pbstarttm": "1631098029"
    "hasAds": "1",  
 
    "subbrand": "c05",
 
    "progen": "CV"
 
 
}</syntaxhighlight>
 
}</syntaxhighlight>
  
===== Ad Metadata =====
+
===== Ad Metadata (optional for DR) =====
The ad metadata should be passed for each individual ad.
+
The Ad Metadata (if applicable) should be passed for each individual ad.
  
 +
Note: All metadata values should be passed as UTF-8 strings.
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! Keys !! Description !! Values !! Required
+
! Keys !! Description !! Values !! Required
 
|-
 
|-
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes
+
| type || type of Ad || <code>"preroll"</code>, <code>"midroll"</code>, <code>"postroll"</code> <br> <code>"ad"</code>  - If specific type can not be identified.||
 
|-
 
|-
| assetid || unique ID assigned to ad || custom || Yes
+
| assetid || unique ID assigned to Ad || custom<br>(no [[Special Characters]]) ||
 
|}
 
|}
  
Line 239: Line 283:
 
"ad": {
 
"ad": {
 
   "type": "preroll",
 
   "type": "preroll",
   "assetid": "AD-ID123"
+
   "assetid": "unique_preroll_ad_id"
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 254: Line 298:
 
! Event !! Description
 
! Event !! Description
 
|-
 
|-
| <code>"playhead"</code> || Playhead position in seconds, must be passed as a whole number every 10 seconds. The final playhead position should be sent before an asset has changed to properly capture full duration. When content is paused, stop passing playhead position until content is resumed. On playhead scrubbing, send current playhead position, followed by the playhead position the user scrubs to. For Live streams, you may use Unix Time (in seconds) as the playhead position. Note that ad playheads must also use Unix Time if Unix Time is used for content playheads.
+
| <code>"playhead"</code> ||  
 +
 
 +
===== Handling Playhead =====
 +
 
 +
Calling <code>"playhead"</code> is critical for accurate duration crediting. You can reference the below guidance to determine the correct playhead position to pass depending on the playback scenario.
 +
 
 +
'''General'''
 +
* Playhead position in seconds, must be passed as a whole number every 10 seconds.  
 +
* The final playhead position should be sent before before sending "complete" event when content playback is complete.  
 +
 
 +
'''Live Stream'''
 +
* For Live streams, use Unix Time (in seconds) matching the broadcast time as the playhead position. Note that ad playheads must also use Unix Time for each single Ad in an Ad Pod.
 +
 
 +
'''VoD Stream'''
 +
* For VoD stream use the player position for Content and Ad at playback start of a content or single Ad in an Ad Pod, playheads will then be 0, 10, 20, ....
 +
 
 +
'''End of an Asset'''
 +
* Final postion must be sent at the end of Content or Ad playback
 +
 
 +
'''Ads'''
 +
* The final playhead position must be sent when switching from content to ad, or ad to content.
 +
* For Ad Pods, playhead must be called for each individual ad.
 +
* When content has resumed following a mid-roll ad break, the next playhead position must continue where the previous content segment left off.
 +
 
 +
'''User Actions'''
 +
* SCRUBBING: Upon user scrubbing, the current position must be sent before a user scrubs, and the new position should be sent where the user lands, and begin sending in the 10 second updates thereafter.
 +
* PAUSE: When content is paused, send current playhead position and stop passing playhead position until content is resumed.
 +
* EXIT Stream: If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.
 +
 
 
|-
 
|-
 
| <code>"complete"</code> || The complete event must be sent when the content has completed full playback. Before calling the complete event, a final playhead update with the final position is required to be sent to receive full duration credit. For Live streams, a complete event must be sent at program boundaries.
 
| <code>"complete"</code> || The complete event must be sent when the content has completed full playback. Before calling the complete event, a final playhead update with the final position is required to be sent to receive full duration credit. For Live streams, a complete event must be sent at program boundaries.
Line 269: Line 341:
 
! Parameter !! Description !! Value !! Required
 
! Parameter !! Description !! Value !! Required
 
|-
 
|-
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes
+
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> ||
 
|-
 
|-
| <code>"position"</code> || playhead position in seconds or Unix time in seconds || <code>"300"</code> || Yes
+
| <code>"position"</code> || playhead position in seconds or Unix time in seconds || <code>"300"</code> ||
 
|-
 
|-
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes
+
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> ||
 
|-
 
|-
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes
+
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> ||
 +
|-style="background-color:#d0f6f8;"
 +
| <code>"sessid"</code> || Unique View Session ID must be created upon start of each stream playback, sessid is unique per video play. || <code>"xxxjavd6wzirm93xb95uxjy1ac5wu1627638609"</code> || ✓
 
|}
 
|}
  
Line 291: Line 365:
 
   "position": [playheadPosition], //position in seconds
 
   "position": [playheadPosition], //position in seconds
 
   "type": [asset type], // values are "content" or "ad"
 
   "type": [asset type], // values are "content" or "ad"
   "utc": "1472760000000" //unix timestamp in milliseconds
+
   "utc": "1472760000000", //unix timestamp in milliseconds
 +
  "sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
Line 297: Line 372:
 
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.
 
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.
  
===== Sample Event Lifecycle =====
+
===== Sample Event Lifecycle for VoD Stream =====
 
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.
 
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.
  
Line 326: Line 401:
  
  
'''Sample Event Lifecycle - Detailed Storyline'''
+
'''Sample Event Lifecycle for VoD Stream - Detailed Storyline'''
 
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.
 
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.
 
<syntaxhighlight lang='javascript'>// SESSION STARTS
 
<syntaxhighlight lang='javascript'>// SESSION STARTS
Line 373: Line 448:
 
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight>
 
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight>
  
 
=====Handling Playhead=====
 
Calling <code>"playhead"</code> is critical for accurate duration crediting. You can reference the below guidance to determine the correct playhead position to pass depending on the playback scenario.
 
 
'''Playhead: General'''
 
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.
 
* Final postion must be sent at the end of content or an ad
 
* Playheads should be sent in seconds only, not milliseconds
 
 
'''Playhead: Ads'''
 
* The final position must be sent when switching from content to ad, or ad to content.
 
* Each ad playhead position should be 0 at ad start.
 
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad.
 
* The last content position before an Ad should be sent before switching to Ads.
 
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.
 
 
'''Playhead: User Actions'''
 
* Upon user scrubbing, the current position must be sent before a user scrubs, and the new position should be sent where the user lands, and begin sending in the 10 second updates thereafter.
 
* On pause, send the current position and then discontinue sending playhead event updates.
 
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.
 
  
 
===== Interruption Scenarios =====
 
===== Interruption Scenarios =====
Line 414: Line 469:
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
// 1. Create Session ID
 
// 1. Create Session ID
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator
+
sessionID = LsTYTmZQPwdchsNZkdtJp9lErjgAp1632729088 // Example sessionID created using a UUID Generator
  
 
// 2. Define URL Structure with App ID and Session ID
 
// 2. Define URL Structure with App ID and Session ID
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=
+
sessionURL = https://sc-eucert.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=
  
 
// 3. Configure Payload
 
// 3. Configure Payload
Line 423: Line 478:
 
payload = {
 
payload = {
 
  "devInfo": {
 
  "devInfo": {
   "devId": "AD-ID",  
+
   "devId": "AD-ID",
 
   "apn": "AppName",
 
   "apn": "AppName",
 
   "apv": "1.0",
 
   "apv": "1.0",
   "uoo": "false"
+
   "fpid": "U4EDwDcpvWIbguYVyjlhzS1v0eaov1631180980",
 +
  "fpcrtm": "1631098029000"
 
   },
 
   },
 
    
 
    
Line 438: Line 494:
 
       "title": "Episode Title S3 - EP1", // episode name
 
       "title": "Episode Title S3 - EP1", // episode name
 
       "length": "1800", // content duration in seconds
 
       "length": "1800", // content duration in seconds
      "segB": "Custom Segment B", // custom segment
 
      "segC": "Custom Segment C", // custom segment
 
      "crossId1": "Standard Episode ID", // episode ID
 
      "crossId2": "Content Originator ID", // content orginator (required for distributors)
 
 
       "airdate": "20161013 20:00:00", // airdate
 
       "airdate": "20161013 20:00:00", // airdate
       "adloadtype": "2", // ad load flag
+
       "adloadtype": "2" // ad load flag,
       "hasAds": "1", // content contains ads = 1 / no ads = 0
+
      "subbrand": "c05",
       "progen": "CV" // program genre abbreviation
+
      "stationId": "TESTXXYYSSWWLL",
 +
       "islivestn": "y",
 +
       "pbstarttm": "1631098029",
 
     },
 
     },
 
     "ad": {
 
     "ad": {
Line 457: Line 511:
 
   "position": "300", // position in seconds
 
   "position": "300", // position in seconds
 
   "type": "content", //"content" or "ad"
 
   "type": "content", //"content" or "ad"
   "utc": "1456448742000" //unix timestamp in milliseconds  
+
   "utc": "1456448742000", //unix timestamp in milliseconds  
 +
  "sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609" // unique for each video play
 
}
 
}
  
 
// Append payload to URL
 
// Append payload to URL
var image = new Image()
+
function sendPayloadToNielsen() {
image.onerror = function() {
+
  var payloadStr  = JSON.stringify(payload); // payload as string
  // wait and send again
+
  var imgPing = new Image();
 +
  imgPing.onload = function() {
 +
    // onload event, payload succesfull sent
 +
  };
 +
  imgPing.onerror = function() {
 +
    // handle error i.e. wait and send again
 +
  };
 +
  imgPing.src = sessionURL+encodeURIComponent(payloadStr);
 
}
 
}
(new Image).src = sessionURL+encodeURIComponent(JSON.stringify(payload));
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Line 510: Line 571:
 
|}
 
|}
  
== Opt-Out ==
+
== Review the Reference Implementation for VoD and Live Streams ==
Your app must provide a means for the user to Opt-Out, or Opt-In to Nielsen Measurement. This requirement can be fulfilled by checking the device OS for the user's setting of "Limit Ad Tracking" or similar option. If the device offers "Limit Ad Tracking" settings, you should set <code>uoo=true</code> or <code>uoo=false</code> depending on the user's privacy setting. Also, ensure that the <code>devId</code> is set to a blank value if the user elects to opt-out.
 
  
If the device does not have OS-level "Do Not Track" settings, you can implement opt-out by creating an Opt-Out/Opt-In button, toggle switch, or slider within the app "Settings", or "About" section to allow the user selection.
+
The Reference Implementation covers vod and Live use cases.
 +
It also covers DAI (Dynamic Ad Insertion) with  preroll and postroll Ads.
  
[[File:Nielsen Opt-Out.png|link=]]
+
In order to start live stream select the checkbox "isLive" in the <code>Playback Settings</code> below the video player.
  
You will need to store the User Opt-Out (uoo) status, so that it can be retrieved and populated in the <code>"devInfo"</code> metadata which will be sent in every Cloud API event (playhead, complete, & delete).
+
Start the Reference Implementation for DK [https://nielsenonlinesupport.com/dk/cloudapi/index.htm?debug=true RefImplCloudAPIDK].
 +
<blockquote>
 +
Review the Nielsen CloudAPI Call Sequence below the Video Player.
 +
</blockquote>
  
{| class="wikitable"
+
== Disclose Nielsen Privacy Statement ==
|-
 
! uoo Key !! Description !! Values
 
|-
 
| uoo || Device is Opted-In to Nielsen Measurement (Recommended Default Setting) || <code>"false"</code>
 
|-
 
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code>
 
|}
 
  
===== devInfo Opt-In JSON Payload Example =====
+
In order to disclose Nielsen measurement privacy statement, please include the following items in your privacy policy:
 
+
* A notice that the player includes third party measurement software that allows users to contribute to market research with anonymous data.
<syntaxhighlight lang="javascript">
+
* A link to the Nielsen Digital Measurement Privacy Policy located at https://sites.nielsen.com/priv/browser/dk/da/DigitalMeasurement.html .
"devInfo": {
 
    "apn": "Cloud API Sample App",
 
    "apv": "1",
 
    "devId": "7be25cf9-8c40-5cc2-871e-19bf41940288",
 
    "uoo": "false"
 
  },
 
</syntaxhighlight>
 
 
 
===== devInfo Opt-Out JSON Payload Example =====
 
 
 
<syntaxhighlight lang="javascript">
 
  "devInfo": {
 
    "apn": "Cloud API Sample App",
 
    "apv": "1",
 
    "devId": "", //devId must be blank when a user elects to Opt-Out.
 
    "uoo": "true"
 
  },
 
</syntaxhighlight>
 
 
 
===== Privacy Information Template To Include In Opt-Out Screen =====
 
 
 
 
 
Additionally, all applications must display the Nielsen privacy policy within their application, typically in the Settings/About screen of your application.  
 
  
 
== Testing ==
 
== Testing ==
Line 564: Line 598:
 
*Asset metadata for both content, and ads
 
*Asset metadata for both content, and ads
 
*Events
 
*Events
*Opt-Out status
 
  
 
=== Player Events ===
 
=== Player Events ===
Line 570: Line 603:
  
 
==== playhead ====
 
==== playhead ====
*Playhead position updates every 10 seconds starting at position '0' for each new asset.
+
*Playhead position updates every 10 seconds starting at position '0' for each new asset for VoD stream and UTC Unix Time in seconds for Live stream.
 
*Final playhead position is sent on content, or ad before switching between assets.
 
*Final playhead position is sent on content, or ad before switching between assets.
 
*Content metadata remains constant throughout an episode, or clip play.
 
*Content metadata remains constant throughout an episode, or clip play.
Line 592: Line 625:
 
==== HTTP Response ====
 
==== HTTP Response ====
 
*Make sure that each of the Cloud API Get requests are received by the Nielsen Cloud API properly through use of the HTTP Response Code outputs enabled in console.
 
*Make sure that each of the Cloud API Get requests are received by the Nielsen Cloud API properly through use of the HTTP Response Code outputs enabled in console.
 
==== Opt-Out ====
 
*Test the "uoo" key gets populated accurately for both Opt-In and Opt-Out selections by validating the Cloud API events called after the user Opt-Out/Opt-In selection.
 
*Test that the devId field is populated with a blank value if a user has elected to Opt-Out. For example: "devId": "",
 
*If the device supports "Limit Ad Tracking" or has device "Opt-Out" settings, test that uoo=true, and that devId is set to a blank value if enabled in the device settings.
 
  
 
== Go Live ==
 
== Go Live ==
Line 603: Line 631:
 
'''Change Endpoint:''' You will need to update to the production endpoint:
 
'''Change Endpoint:''' You will need to update to the production endpoint:
  
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code>
+
*Testing: <code>https://sc-eucert.nmrodam.com/nmapi/v2/</code>
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code>
+
*Production: <code>https://capi-dmk.nmrodam.com/nmapi/v2/</code>
  
 
Your production URL structure should now be:
 
Your production URL structure should now be:
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code>
+
<code>https://capi-dmk.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code>
  
 
'''Disable Logging:''' You can now disable debug logging
 
'''Disable Logging:''' You can now disable debug logging

Revision as of 07:56, 27 September 2021

Engineering Portal breadcrumbArrow.png Digital breadcrumbArrow.png International DCR breadcrumbArrow.png DCR Denmark Video Cloud API

DCR Integration Utilizing Cloud API

This guide shows you how to integrate the Nielsen Cloud API to enable Digital Content Ratings (DCR), and fuel other measurement products on your over-the-top (OTT) Apps.

Prerequisites

To get started, you will need a Nielsen App ID. The App ID is a unique ID assigned to your app. This will be provided to you by your assigned Technical Account Manager upon starting the integration.

Item Description Source
App ID (appid) Unique ID assigned to the player/site and configured by product. Provided by Nielsen

Integration

We will cover the steps for constructing the Cloud API Calls.

URL Structure

The Cloud API Calls are HTTP GET Requests with the URL structure:

[endpoint]/[appid]/[sessionID]/a?b=[payload]

The URL includes the following components:

  • [endpoint]: location of data collection environment
  • [appid]: provided App ID
  • [sessionID]: unique value for each user session
  • [payload]: metadata and events

Endpoint

There are endpoints for testing and production:

During testing, all calls should be pointed to the testing endpoint. We will review the update to the production endpoint during the Go Live section of this guide.

URL Example

As you move through the integration steps, you can reference the below URL structure with the expanded payload:

https://sc-eucert.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=
{
  "devInfo": [deviceInfo],
  "metadata": {
    "content": [content_metadata],
    "ad": [ad metadata]
  },
  "event": [event],
  "position": [playhead_position],
  "type": [asset type],
  "utc": [Unix time in ms],
  "sessid": [unique view session ID for each video play]
}

Create Session ID and send EMM Ping

Create Session ID

A unique Session ID [sessionID] must be created upon app launch and provided in the URL. This will allow measurement to occur for the entire duration that a user is within the app.

A Session ID needs to be completely unique so it is recommended to use a version 4 UUID or another method of your choosing to guarantee there are no repeats, also see Reference Implementation for VoD and Live Streams for your reference and use.

Upon exiting the app, the session will need to be terminated using the delete event. Sessions will automatically expire after 30 minutes of cloud inactivity.

Send EMM Ping

An EMM Ping must be sent using the created unique Session ID [sessionID] upon start of the first stream playback.

https://[sessionID].uaid.nmrodam.com/

Also see Reference Implementation for VoD and Live Streams for your reference.

Create First Party ID

  • An First Party ID [fpid] must be created and stored on the device. It is re-used until expiration date or if the user has deleted it on from the device storage.

The default expiration date should be set to the equivalent of 180 days.

  • Additionally the Creation Time [fpcrtm] of the First Party ID should be stored as well. The same value should be used as long as the First Party ID is available on the device.

Create View Session ID for each Video Start

An View Session ID [sessid] must be created upon start of each stream playback, sessid is unique per video play.

Define URL Structure

Define the URL structure using your provided [appid] and a unique [sessionID].

https://sc-eucert.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]

Configure Payload

All Cloud API requests must contain the following payload data:

  • devInfo: device and app info
  • metadata: asset metadata
  • event metadata: type of event

The payload can be passed through key-values using the Nielsen reserved keys. The specific keys and descriptions are highlighted in the tables included in this section.

Payload Example

The example below should be referenced when following the steps for configuring the request payload.

// 3.1 Configure Payload: devInfo 
payload = {
    "devInfo": {
        "devId": "AD-ID", 
        "apn": "AppName",
        "apv": "1.0",
        "fpid": "First Party ID",
        "fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"
    },
    
    // 3.2 Configure Payload: metadata
    "metadata": {
        "content": { // object for measuring video content
            "type": "content", // "content" for video
            "assetid": "VIDEO-ID123", // unique ID for video
            "isfullepisode": "y", // full episode flag
            "program": "Program Name", // program name
            "title": "Episode Title S3 - EP1", // episode name
            "length": "1800", // content duration in seconds
            "airdate": "20161013 20:00:00", // airdate
            "adloadtype": "2", //ad load flag
            "subbrand": "c05", // channel ID or subrand provided by Nielsen
            "stationId": "TESTXXYYSSWWLL",
            "islivestn": "y",
            "pbstarttm": "1631098029"
        },
        "ad": {
            "type": "preroll", // type of ad
            "assetid": "AD-ID123" // unique ID for ad
        }
    },
    
    // 3.3 Configure Payload: events
    "event": "playhead", //event name
    "position": "300", // position in seconds
    "type": "content", //"content" or "ad"
    "utc": "1456448742000", //unix timestamp in milliseconds 
    "sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play
}
Configure Payload: devInfo

An object "devInfo" will need to be created to capture App and Device information.

Keys Description Values Required
devId unique ID to identify user (e.g. Advertising ID, Roku Device ID) custom
apn app name custom
apv app build version custom
fpid First Party ID custom
fpcrtm Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds) custom

Example devInfo Object

// create devInfo object
"devInfo": {
  "devId": "AD-ID",
  "apn": "AppName",
  "apv": "1.0",
  "fpid": "First Party ID",
  "fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"
},

3.2 Configure Payload: metadata

Asset metadata can be passed through "metadata". There are two asset types: "content" for video and "ad" for ads. The metadata received for each asset is used for classification and reporting.

You will need to set up "metadata" objects for "content" and "ad" with the required Nielsen keys as shown in the sample code below.

Content Metadata

Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.


program and title metadata values should be passed to SDK as UTF-8 strings.

Keys Description Values Required
type type of asset "content" for main content
assetid unique ID assigned to asset custom
(no Special Characters)
program name of program custom
title episode name custom
length length of content in seconds Length of content in seconds (86400 seconds for live stream (24/7). For Event-Live streams planned length. For VoD video length)
airdate the original date (local time with hh:mm:ss as 24h time stamp) content became available. This date does not change if the content is rebroadcasted on linear TV. YYYYMMDD HH:MI:SS (if not known set it to eg. "19700101 00:00:00")
isfullepisode full episode flag
  • "y" full episode (full content for a program)
  • "n" non full episode (only one part of the entire content for a program , i.e. preview, sub-episodes)

adloadtype type of Ad load
  • "1" Linear - matches TV ad load
  • "2" Dynamic - Dynamic Ad Insertion (DAI)

stationId Unique Gracenote Station ID generated by Nielsen that uniquely identifies a live channel

provided by Nielsen

islivestn Indicates if a stream is playing on a live channel
  • "y" playing on a live channel
  • "n" otherwise i.e. VoD

pbstarttm Playback Start Time (UTC): Unix timestamp in seconds matching the broadcast time for Content and Ad when a user starts and joins a live stream (seconds since Jan-1-1970 UTC)

i.e. "1631098029" for live stream and ""(empty string) for a VoD.

subbrand vcid/sub-brand/Channel ID – value is automatically populated through provided AppID. In order to override the sub-brand configured to the App ID, value can be passed here (e.g. multiple sub-brands/Channels in the App)

provided by Nielsen


Example Content Object

// create content object
"content": {
  "type": "content",
  "assetid": "unique_content_id",
  "program": "program name",
  "title": "episode title",
  "length": "length in seconds",
  "airdate": "20200713 10:22:00",
  "isfullepisode": "y",
  "adloadtype": "2",
  "subbrand": "c05",
  "stationId": "TESTXXYYSSWWLL",
  "islivestn": "y",
  "pbstarttm": "1631098029"
}
Ad Metadata (optional for DR)

The Ad Metadata (if applicable) should be passed for each individual ad.

Note: All metadata values should be passed as UTF-8 strings.

Keys Description Values Required
type type of Ad "preroll", "midroll", "postroll"
"ad" - If specific type can not be identified.
assetid unique ID assigned to Ad custom
(no Special Characters)
Example Ad Object
// create ad object
"ad": {
  "type": "preroll",
  "assetid": "unique_preroll_ad_id"
}

Configure Payload: Events

The last part of the payload is for enabling events so content is measured correctly when viewed. The events and required parameters are included below.

Event Types

The available events are:

Event Description
"playhead"
Handling Playhead

Calling "playhead" is critical for accurate duration crediting. You can reference the below guidance to determine the correct playhead position to pass depending on the playback scenario.

General

  • Playhead position in seconds, must be passed as a whole number every 10 seconds.
  • The final playhead position should be sent before before sending "complete" event when content playback is complete.

Live Stream

  • For Live streams, use Unix Time (in seconds) matching the broadcast time as the playhead position. Note that ad playheads must also use Unix Time for each single Ad in an Ad Pod.

VoD Stream

  • For VoD stream use the player position for Content and Ad at playback start of a content or single Ad in an Ad Pod, playheads will then be 0, 10, 20, ....

End of an Asset

  • Final postion must be sent at the end of Content or Ad playback

Ads

  • The final playhead position must be sent when switching from content to ad, or ad to content.
  • For Ad Pods, playhead must be called for each individual ad.
  • When content has resumed following a mid-roll ad break, the next playhead position must continue where the previous content segment left off.

User Actions

  • SCRUBBING: Upon user scrubbing, the current position must be sent before a user scrubs, and the new position should be sent where the user lands, and begin sending in the 10 second updates thereafter.
  • PAUSE: When content is paused, send current playhead position and stop passing playhead position until content is resumed.
  • EXIT Stream: If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.
"complete" The complete event must be sent when the content has completed full playback. Before calling the complete event, a final playhead update with the final position is required to be sent to receive full duration credit. For Live streams, a complete event must be sent at program boundaries.
"delete" The delete event is optional and can be sent when the viewing session is terminated (typically on App close). A new session ID must be generated after sending a delete event. Delete should not be sent on app interruptions or foreground/background events. All creditable duration will be summarized for all asset types when delete occurs (content and ads).
Event Parameters

The following parameters need to be passed when calling events:

Parameter Description Value Required
"event" event type "playhead", "complete", or "delete"
"position" playhead position in seconds or Unix time in seconds "300"
"type" asset type "content", "ad"
"utc" Unix timestamp in milliseconds. Must be passed every 10 seconds. "1472760000000"
"sessid" Unique View Session ID must be created upon start of each stream playback, sessid is unique per video play. "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609"
Example Event

You can call events by passing values in the required parameters:

"devInfo": [deviceInfo],
  "metadata": {
    "content": [content metadata],
    "ad": [ad metadata]
  },
  // Event Parameters
  "event": [event], // event name
  "position": [playheadPosition], //position in seconds
  "type": [asset type], // values are "content" or "ad"
  "utc": "1472760000000", //unix timestamp in milliseconds
  "sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play
}

Note: The full payload including "devInfo" and "metadata" must be populated in each event request.

Sample Event Lifecycle for VoD Stream

The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.

// Start of Session: session ID created when App is opened

// Preroll
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} 
 
// Content
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} 

// Midroll
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} 

// Content resumes at 15 minutes
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} 

// Content completes at 30 minutes
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} 
 
// Postroll
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} 

//End of Session: The delete event should be called when the App is exited. The values for position and type not required to be passed.
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"}


Sample Event Lifecycle for VoD Stream - Detailed Storyline This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.

// SESSION STARTS
// Start of Session: session ID created when App is opened

// PREROLL
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} 

// Preroll Stop - End each Ad with the final position of the Ad.
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}
 
// CONTENT 
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} 

// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}

// MIDROLL
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} 

// Midroll Stop - End each Ad with the final position of the Ad.
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}

// CONTENT
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} 

// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} 

Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} 

// POSTROLL
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} 

// Postroll Stop - End each Ad with the final position of the Ad.
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}

// SESSION ENDS

//End of Session: The delete event should be called when the App is exited. The values for position and type not required to be passed.
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"}


Interruption Scenarios

As part of configuring events, you will need to handle all possible interruption scenarios such as:

  • Wi-Fi OFF / ON
  • App going Background / Foreground (Video players only, not for Audio players)
  • App Crash or Exit

When playback is interrupted, the app needs to send delete immediately.

Once playback resumes, a new session will need to be created with a unique session ID. All of the required metadata and events will need to be sent.

Note: The session will automatically timeout after 30 minutes of inactivity.

Example Request

Now that we walked through the Cloud API integration steps, your requests should have the following components: Session ID, App ID, and Payload. You can reference the example below when your reviewing your integration.

// 1. Create Session ID
sessionID = LsTYTmZQPwdchsNZkdtJp9lErjgAp1632729088  // Example sessionID created using a UUID Generator

// 2. Define URL Structure with App ID and Session ID
sessionURL = https://sc-eucert.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=

// 3. Configure Payload
// 3.1 Configure Payload: devInfo 
payload = {
 "devInfo": {
   "devId": "AD-ID",
   "apn": "AppName",
   "apv": "1.0",
   "fpid": "U4EDwDcpvWIbguYVyjlhzS1v0eaov1631180980",
   "fpcrtm": "1631098029000"
  },
  
  // 3.2 Configure Payload: metadata
  "metadata": {
    "content": { // object for measuring video content
      "type": "content", // "content" for video
      "assetid": "VIDEO-ID123", // unique ID for video
      "isfullepisode": "y", // full episode flag
      "program": "Program Name", // program name
      "title": "Episode Title S3 - EP1", // episode name
      "length": "1800", // content duration in seconds
      "airdate": "20161013 20:00:00", // airdate
      "adloadtype": "2" // ad load flag,
      "subbrand": "c05",
      "stationId": "TESTXXYYSSWWLL",
      "islivestn": "y",
      "pbstarttm": "1631098029",
    },
    "ad": {
      "type": "preroll", // type of ad
      "assetid": "AD-ID123" // unique ID for ad
    }
  },
    
  // 3.3 Configure Payload: events
  "event": "playhead", //event name
  "position": "300", // position in seconds
  "type": "content", //"content" or "ad"
  "utc": "1456448742000", //unix timestamp in milliseconds 
  "sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609" // unique for each video play
}

// Append payload to URL
function sendPayloadToNielsen() {
  var payloadStr  = JSON.stringify(payload); // payload as string
  var imgPing = new Image();
  imgPing.onload = function() {
    // onload event, payload succesfull sent
  };
  imgPing.onerror = function() {
    // handle error i.e. wait and send again
  };
  imgPing.src = sessionURL+encodeURIComponent(payloadStr);
}

Enable Debug Logging

Now that you have set up the Cloud API requests, you can enable debug logging to validate your integration. Enabling debug logging is required for Nielsen certification.

GET Request

Display GET Request to console using a name to identify each event (e.g. playhead).

console.log("Event", image);

Payload

Output payload to identify required metadata and events.

console.log("Event Payload", payload);

HTTP Response Code

Confirm request was completed by viewing HTTP response code.

code = msg.GetResponseCode();
console.log("Response Code", code);

You can reference the HTTP Response Code table when reviewing your requests:

Status Code Status Text Description
200 OK request received
403 Forbidden invalid App ID
404 Not Found JSON issue

Review the Reference Implementation for VoD and Live Streams

The Reference Implementation covers vod and Live use cases. It also covers DAI (Dynamic Ad Insertion) with preroll and postroll Ads.

In order to start live stream select the checkbox "isLive" in the Playback Settings below the video player.

Start the Reference Implementation for DK RefImplCloudAPIDK.

Review the Nielsen CloudAPI Call Sequence below the Video Player.

Disclose Nielsen Privacy Statement

In order to disclose Nielsen measurement privacy statement, please include the following items in your privacy policy:

Testing

Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.

Payload Validation

Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:

  • devInfo
  • Asset metadata for both content, and ads
  • Events

Player Events

Review event calls:

playhead

  • Playhead position updates every 10 seconds starting at position '0' for each new asset for VoD stream and UTC Unix Time in seconds for Live stream.
  • Final playhead position is sent on content, or ad before switching between assets.
  • Content metadata remains constant throughout an episode, or clip play.
  • Ad metadata is populated appropriately for each individual ad.
  • Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.
  • For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.
  • Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.
  • Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.

complete

  • Check that the complete event executes upon content complete after the final playhead update is sent
  • Do not execute the complete event for ads

delete

  • Check to see that the delete event occurs upon app exit, if the platform has the necessary exit callback events.

GET Request Format

  • Ensure that the event payloads are formatted in JSON
  • Check to see that each of the Cloud API GET requests are properly encoded

HTTP Response

  • Make sure that each of the Cloud API Get requests are received by the Nielsen Cloud API properly through use of the HTTP Response Code outputs enabled in console.

Go Live

After your integration has been certified, you will need to: Change Endpoint and Disable Logging.

Change Endpoint: You will need to update to the production endpoint:

Your production URL structure should now be: https://capi-dmk.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]

Disable Logging: You can now disable debug logging