https://engineeringportal.nielsen.com//w/api.php?action=feedcontributions&user=LaMarHolmes&feedformat=atomEngineering Client Portal - User contributions [en]2024-03-29T07:11:07ZUser contributionsMediaWiki 1.32.2https://engineeringportal.nielsen.com//w/index.php?title=Radio&diff=6644Radio2023-11-27T18:18:51Z<p>LaMarHolmes: </p>
<hr />
<div>{{Banner|Nielsen Audio Support|Radio}}<br />
<br />
__NOTOC__<br />
{{Alert| '''Product Notification:'''<br><br />
'''''MCEM FIRMWARE 1.5.2.07 NOW AVAILABLE''''' <br><br />
'''''Official release notification: [https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel+Encoding+Monitor/Information+Bulletin+206.pdf INFORMATION BULLETIN 206 - RELEASE OF MCEM FIRMWARE 1.5.2.07 ]'''''}}<br />
<br />
=== Multi-Channel Encoding Monitor ===<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
<br />
|-<br />
| '''MCEM - Product Overview'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/Product%20Overview%20-%20Multi-Channel%20Encoding%20Monitor.pdf MCEM - Product Overview]<br />
<br />
|-<br />
| '''MCEM - Quick Reference Guide'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM-Quick%20Reference%20Guide.pdf MCEM - Quick Reference Guide]<br />
<br />
|-<br />
| '''MCEM - Instructions for Confirming Connectivity'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://engineeringportal.nielsen.com/w/docs/MCEM-Instructions_for_Confirming_Connectivity.pdf MCEM - Instructions for Confirming Connectivity]<br />
<br />
|-<br />
| '''MCEM 1.5.2.07 Firmware Download and Instructions'''<br />
|| {{SmallIcon|ZipIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel+Encoding+Monitor/MCEM+1_5_2_07+Firmware+Instructions+Manual+2022+March+2.zip MCEM 1.5.2.07 Firmware Manual Instructions 2022 March]<br />
<br />
|-<br />
| '''MCEM - Activating Email Alerting'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel+Encoding+Monitor/Activating%20Email%20Alerting%20on%20the%20MCEM.pdf MCEM - Activating Email Alerting]<br />
<br />
|-<br />
| '''MCEM - Data and Analytics'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/Multi-Channel%20Encoding%20Monitor%20Data%20and%20Analytics.pdf MCEM - Data and Analytics]<br />
<br />
|-<br />
| '''MCEM - User Manual'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20Equipment%20Manual%20S%20Revision%20M%20.pdf MCEM - User Manual]<br />
<br />
|-<br />
| '''MCEM - Encodability and Detectability'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20-%20Encodability%20View%20and%20Detectability%20Confidence%20History%20-%20How%20to%20Access%20CSV%20Files.pdf MCEM - Encodability View and Detectability Confidence History]<br />
<br />
|-<br />
| '''MCEM Order Form'''<br />
|| {{SmallIcon|SheetIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20Order%20Form%20e1.xlsx MCEM Order Form]<br />
<br />
<br />
|}<br />
<br />
=== Nielsen Audio Software Encoder ===<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
<br />
|-<br />
| The Nielsen Audio Software Encoder is available for integration into 3rd party broadcasting equipment. More information can be found [[Nielsen_Audio_Software_Encoder|here]].<br />
|}<br />
<br />
=== AnaDig 1212 Encoder ===<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
<br />
| '''PPM Encoding Best Practices'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/AnaDig%201212%20Encoder/PPM%20Encoding%20Best%20Practices.pdf PPM Encoding Best Practices]<br />
<br />
|-<br />
| '''AnaDig 1000-1212 Encoder Equipment Manual'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/AnaDig%201212%20Encoder/Equipment%20Manual,%20AnaDig%20Encoder%20(1050-1645%20RevE).pdf Equipment Manual, AnaDig Encoder (1050-1645 RevE)]<br />
<br />
|-<br />
| '''Firmware AnaDig1212 Encoder v1.0.3.1'''<br />
|| {{SmallIcon|ZipIcon.png}} || <br />
* [https://nielsendownloads-blue.digitalengsdk.com/radio/AnaDig%201212%20Encoder/Firmware_AnaDig1212__Encoder_Version_1.0.3.1%20(1096-1284_Rev_A).zip Firmware_AnaDig1212__Encoder_Version_1.0.3.1 (1096-1284_Rev_A)]<br />
|}<br />
<br />
=== Digital (AES) Encoder ===<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
| '''Digital (AES) Encoder Equipment Manual (1050-1475 RevF)'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Digital%20(AES)%20Encoder/Digital%20(AES)%20Encoder%20Equipment%20Manual%20(1050-1475%20RevF).pdf Digital (AES) Encoder Equipment Manual (1050-1475 RevF)]<br />
|}<br />
<br />
=== Analog Encoder ===<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
<br />
|-<br />
| '''Analog Encoder Equipment Manual (1050-1473 RevF)'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Analog%20Encoder/Analog%20Encoder%20Equipment%20Manual%20(1050-1473%20RevF).pdf Analog Encoder Equipment Manual (1050-1473 RevF)]<br />
<br />
|}<br />
<br />
{{CategoryIcon|DiagnosisToolsIcon.png|Diagnostic Tools}}<br />
{| class="wikitable"<br />
|-<br />
! style="width: 75px;" |<br />
! style="width: 35%;" | Software<br />
! style="width: 45px;" | OS <br />
! Download <br />
<br />
|-<br />
<br />
| {{SmallIcon|NACATIcon.png}} <br />
|| '''[[Nielsen Audio Code Analysis Tool 2|Nielsen Audio Code Analysis Tool 2 (NACAT2)]]''' <br />
|| {{OSIcon|WindowsIcon.png}} || <br />
{{TVDownloadRequestLink|name=NACAT2 1.4|dlid=83d58832e663a21841b32f771cc2781ae5b5b572&section=r}}<br />
<br />
|-<br />
<br />
<br />
<!--<br />
{| class="wikitable"<br />
|-<br />
!International Radio/Audio Documentation<br />
|-<br />
| '''[[International_Audio|International Audio]]'''<br />
|}<br />
--></div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=Nielsen_Audio_Code_Analysis_Tool_3&diff=6606Nielsen Audio Code Analysis Tool 32023-11-07T16:46:29Z<p>LaMarHolmes: Created page with "Category:TV {{Breadcrumb|}} {{Breadcrumb|TV}} {{CurrentBreadcrumb}} '''Nielsen Audio Code Analysis Tool 3 (NACAT3)'''— is a software that captures audio, decodes Nielse..."</p>
<hr />
<div>[[Category:TV]]<br />
{{Breadcrumb|}} {{Breadcrumb|TV}} {{CurrentBreadcrumb}}<br />
<br />
'''Nielsen Audio Code Analysis Tool 3 (NACAT3)'''— is a software that captures audio, decodes Nielsen audio codes, logs and displays the information to the user. The Nielsen EVS department uses the NACAT application for monitoring, assisting in troubleshooting and verifying NAVE encoder installations. The primary information that is decoded by NACAT are program content (PC), final distributor (FD), time stamp, encoded channel (left or right), source identification number (SID), type of encoding (commercial or non-commercial) and DST or standard time.<br />
<br />
== Software Downloads ==<br />
{{TVDownloadRequestLink|name=NACAT3 3.0.0.1|dlid=5e5c74d05d0530f000c69506e23bc3da2e63eb32}}</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DAR_Tag_Implementation_Guide&diff=6387DAR Tag Implementation Guide2023-06-12T18:19:00Z<p>LaMarHolmes: /* HEM Support (Hashed Email) */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
<br />
= Introduction =<br />
<br />
This document provides an overview of the Nielsen Digital Ad Ratings (DAR) Tags and the steps necessary to implement them as part of your digital advertising campaigns.<br />
=== What is DAR ===<br />
DAR is a measurement platform for digital advertising campaigns. The platform provides a clear view of the true audience of a campaign, including Reach, Frequency, and GRP statistics by audience demographic group. <br />
=== What we measure=== <br />
All DAR tags allow you to measure campaign impressions and the DAR JavaScript tags measure ad viewability, GIVT (General Invalid Traffic), and SIVT (Sophisticated Invalid Traffic) across platforms including web, mobile, and in-app.<br />
=== How we measure it=== <br />
Nielsen’s DAR suite of JavaScript tags together with a pixel tag fallback will be present in your ad placements. We utilize industry-standard APIs to perform measurement cross-browser and cross-platform. In most cases, you will only need to add a simple URL through your ad management interface to fully utilize DAR measurement in your campaigns.<br />
=== Prerequisites ===<br />
For steps outlined in this document, you should have access to Nielsen’s Campaign Management Interface (CMI) and a Nielsen Technical Account Manager (TAM) will be working with you during the implementation phase.<br />
__TOC__<br />
= DAR Measurement Types =<br />
<br />
== DAR Display== <br />
<br />
The DAR Display JavaScript tag reports ad impressions as well as measures ad viewability and SIVT. In standard web placements, it will find the ad unit in the surrounding DOM container and will then report viewability as a time series with a 1-second resolution.<br />
<br />
The DAR tag will report the MRC-required minimum of 1 second on screen and a continuous viewability time series for the lifetime of the ad session to enable additional viewability qualifiers.<br />
<br />
The tag can utilize the IAB’s [https://iabtechlab.com/standards/open-measurement-sdk/ '''Open Measurement SDK'''] (OM SDK) including [https://iabtechlab.com/blog/open-measurement-for-web-video-arrives/ '''OM Web'''] integration if the OM Interface Definition (OMID) is available, or it will use industry-standard web APIs to measure viewability.<br />
<br />
=== Requirements ===<br />
<br />
The DAR Display tag requires a JavaScript-enabled browser for web environments or the OM SDK for in-app to operate and should be placed close to the corresponding measured ad unit. It should be on the same DOM level (e.g. directly under the same parent) or in a child node under the same parent node. The ad unit should be a content-bearing DOM element (e.g. img, canvas, SVG, iframe, div) with a minimum size of 30x30 pixels.<br />
<br />
=== Parameters ===<br />
<br />
The minimum required DAR parameters are '''ca, ci, cr, pc, ce''' and '''am'''. See the [[DAR_Tag_Implementation_Guide#Appendix|'''Appendix''']] for a full list of parameters.<br />
<br />
=== Example Tag ===<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript" <br />
src="https://dar.imrworldwide.com/js/dar.js?ca=nlsnXXXXXX&cr={AD.ID}&ce={PUBLISHER.ID}&ci=nlsnciXXXX&pc={PLACEMENT.ID}&am=3"><br />
</script><br />
</syntaxhighlight><br />
<br />
=== Example OMID Display Placement ===<br />
<br />
DAR can be enabled through the OM SDK by passing the required Nielsen OM inputs listed in the table below during setup:<br />
<br />
{| class="wikitable" <br />
|-<br />
! style="width: 20%" | OM Parameter<br />
! style="width: 40%" | Description<br />
! style="width: 40%" | Nielsen Value<br />
! style="width: 5%" |Required<br />
|-<br />
| Vendor Key<br />
| ID for measurement provider<br />
| nielsen.com-omid<br />
| ✔<br />
|-<br />
| JavaScript Resource URL<br />
| URL for measurement provider’s verification script<br />
|<syntaxhighlight lang="html"> https://dar.imrworldwide.com/js/dar.js</syntaxhighlight><br />
| ✔<br />
|-<br />
| Verification Parameters<br />
| Measurement provider’s verification tag parameters<br />
| style="font-family:'Courier New', Courier, monospace !important; color:#222222;" |<syntaxhighlight lang="html">ca=nlsnXXXXXX&cr={AD.ID}&ce=publisherXXXX&ci=nlsnciXXXX&pc=placementID_XXXX1&am=3</syntaxhighlight><br />
| ✔<br />
|-<br />
| Verification Not Executed URL<br />
| Error URL when the ad player denies measurement script execution<br />
| style="font-family:'Courier New', Courier, monospace !important; color:#222222;" | <syntaxhighlight lang="html">https://events.imrworldwide.com/er?ercd=8800&erms=verificationNotExecuted-<br />
{reason}&ca=nlsnXXXXXX&cr=ad_ID_XXXX&ce=publisherXXXX&<br />
ci=nlsnciXXXX&pc=placementID_XXXX5&am=3<br />
&c13={asid,app_id}</syntaxhighlight><br />
|<br />
<br />
|}<br />
<br />
<blockquote><br />
Note: The verificationNotExecuted Error URL is recommended for better troubleshooting during campaign setup. If your system can provide a macro for the reason of the interrupted measurement session, it can be added in place of the {reason} placeholder in the error URL. This can be an error code or a clear text error message.</blockquote><br />
<br />
=== Expected Display Ad Session Pings ===<br />
{| class="wikitable" <br />
<br />
! '''Description'''<br />
! '''Timing'''<br />
! '''Path'''<br />
|-<br />
| DAR Main Ping<br />
| At initial load<br />
| secure-gl.imrworldwide.com/cgi-bin/m<br />
|-<br />
| Nielsen Measure Ping<br />
| Measurement start<br />
| events.imrworldwide.com/nmp<br />
|-<br />
| Primary Standard Ping<br />
| After 1 second of viewable duration (may not occur based on MRC rules)<br />
| events.imrworldwide.com/psp<br />
|-<br />
| Timed Pings<br />
| At 1, 5, 15 and 120 seconds of ad session time (may not occur based on ad session length)<br />
| events.imrworldwide.com/1sp, 5sp, 15sp, 120sp<br />
|-<br />
| Final Ping<br />
| At window/tab unloading event<br />
| events.imrworldwide.com/fp<br />
|-<br />
| Error Ping<br />
| Potential integration error - please contact your Nielsen representative<br />
| events.imrworldwide.com/er<br />
|}<br />
<br />
=== Ping Flow ===<br />
<br />
This flow illustrates the behavior of the DAR Display tag.<br /><br />
<br />
[[File:Screenshot 2022-06-22 152646.png]]<br />
<br />
{| class="wikitable" <br />
|- <br />
! colspan="2" | Ping Flow Legend<br />
|- <br />
| 1SP, 5SP, 15SP, 120SP<br />
| Timed Measure Ping at 1, 5, 15 and 120 seconds<br />
|- <br />
| D0, D1, D2<br />
| Dynamic SIVT Pings at 1, 15 &amp; 30 seconds<br />
|- <br />
| FP<br />
| Final Ping<br />
|- <br />
| IMPID<br />
| Unique Impression ID<br />
|- <br />
| NMP<br />
| Nielsen Main Measure Ping<br />
|-<br />
| PSP<br />
| Primary Standard Ping<br />
|-<br />
| SIVT<br />
| Sophisticated Invalid Traffic<br />
|}<br />
<br />
== DAR Video == <br />
<br />
The DAR Video tag will typically be trafficked as part of a Video Ad Serving Template (VAST) file. Nielsen provides its wrapped video tag (vWrap) to make this type of deployment easy and consistent across the various ad servers and trafficking options. Nielsen’s vWrap tag supports both automatic OMID and VPAID integration with existing VAST files. The two sections below, [[#Wrapped_Video_Tag_.28vWrap.29_Deployment|'''Wrapped Video Tag''']] and [[#Video_JS_Tag|'''Video JS Tag''']], describe these options and their expected outcomes.<br />
<br />
In addition, Nielsen supports '''direct DAR Video tag deployments''' with manual integration in existing workflows. In this case, the section [[#video-js-tag|'''Video JS Tag''']] below describes the basic setup and expected results. In addition, it is recommended that you work closely with your Nielsen Technical Account Manager if you consider a manual tag integration with your campaigns.<br />
<br />
=== Wrapped Video Tag (vWrap) Deployment ===<br />
<br />
Nielsen’s wrapped DAR video tag, vWrap, is the preferred delivery method for VAST-controlled video ad placements.The vWrap tag is served by a Nielsen service that takes an original VAST with an inline ad (not a wrapper redirect) and dynamically adds the DAR Video tag with measurement solutions for VPAID and OMID. The '''apiframework''' parameter can be used to control which measurement solution will be inserted (see below).<br />
<br />
=== Parameters ===<br />
<br />
The minimum required DAR parameters are '''ca, ci, ce, cr, pc''', '''am, apiframework''' and '''vastURL'''. See the [[DAR_Tag_Implementation_Guide#Appendix|'''Appendix''']] for a full list of parameters.<br />
<br />
The Open Real Time Bidding ([https://iabtechlab.com/wp-content/uploads/2022/04/OpenRTB-2-6_FINAL.pdf '''OpenRTB''']) API framework values for identifying the ad inventory type should be passed in the Nielsen '''apiframework''' parameter. The values should be either 1 or 2 (VPAID) or 7 or 8 (OMID). The available API framework values are listed in the IAB’s [https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/master/AdCOM%20v1.0%20FINAL.md#list--api-frameworks- '''AdCOM specification 1.0''']. If the parameter is left blank or set to 0, Wrap will add the DAR Video tag as '''both''' an OMID verification client and VPAID wrapper. See more details in the [[DAR_Tag_Implementation_Guide#Appendix|'''Appendix''']].<br />
<br />
The '''vastURL''' parameter must be the last parameter on the DAR tag with its value set as the full URL (including all original parameters) of the original VAST tag for the ad placement.<br />
<br />
=== Example Wrapped Video Tag (vWrap) ===<br />
{| class="wikitable" style="font-family:'Courier New', Courier, monospace !important;"<br />
|-<br />
! <syntaxhighlight lang="html"> https://vwrap.imrworldwide.com/v1/wrap?ca=nlsnXXXXXX&cr={AD.ID}&ce={PUBLISHER.ID}&pc={PLACEMENT.ID}&ci=nlsnciXXXX&am=4&<br />
c9={devid,Advertising_ID}&c13=asid,app_id}&apiframework={APIFRAMEWORK}&vastURL={ORIGINAL_VAST_URL}</syntaxhighlight><br />
|}<br />
<blockquote><br />
To observe how vWrap operates, we have provided some example VAST URLs which you can load directly in your browser.<br />
</blockquote><br />
==== VAST ad Unit, no Impression/Viewability ====<br />
First, here is a VAST ad unit with a single video file and no impression tracking or viewability measurement:<br />
{| class="wikitable" <br />
|-<br />
! https://madimator.com/vast-examples/example_video_only_nielsen_15s.xml <br />
|}<br />
==== VAST ad Unit, Nielsen vWrap for OMID measurement ====<br />
This is the same VAST file loaded via Nielsen’s vWrap tag for '''OMID measurement''' (apiframework is set to 7):<br />
{| class="wikitable" <br />
|-<br />
! https://vwrap.imrworldwide.com/v1/wrap?ca=nlsn305255&cr=nielsenomidtest&ce=nielsen&pc=vastomid&ci=nlsntest&am=4&apiframework=7&vastURL=http://madimator.com/vast-examples/example_video_only_nielsen_15s.xml<br />
|}<br />
<br />
==== VAST ad Unit, Nielsen vWrap for VPAID measurement ====<br />
And here is the same VAST with the vWrap tag configured for '''VPAID measurement''' (apiframework is set to 2):<br />
{| class="wikitable" <br />
|-<br />
!https://vwrap.imrworldwide.com/v1/wrap?ca=nlsn305255&cr=nielsenomidtest&ce=nielsen&pc=vastvpaid&ci=nlsntest&am=4&apiframework=2&vastURL=http://madimator.com/vast-examples/example_video_only_nielsen_15s.xml <br />
|}<br />
<br />
=== Video JS Tag ===<br />
<br />
The DAR Video tag supports both OM SDK and VPAID video ad measurement and provides viewability time series, audio volume time series, GIVT, and SIVT data. The time series contains playhead events with corresponding measurements at a 1-second resolution. In addition to the time series, a dedicated ping will report on the MRC-required minimum of 2 seconds on screen.<br />
<br />
With OM SDK, the DAR Video tag supports the following ad types:<br />
<br />
* Native mobile in-app ad placements <br />
* Mobile web ads<br />
* OM Web placements<br />
* OMID-enabled streaming video players with ad SDKs (for instance DAI IMA SDK)<br />
<br />
<br />
With VPAID, it supports the following operating modes:<br />
* As VPAID wrapper for an existing VPAID ad unit in the VAST<br />
* As VPAID ad unit in a VAST with video files and AdParameters node<br />
* In Custom Integrations with VPAID host players<br />
<br />
<br />
<br />
In most cases, the DAR Video tag should not be manually implemented as a wrapper, instead consider utilizing Nielsen’s vWrap tag.<br />
<br />
==== Requirements ====<br />
<br />
The DAR Video tag needs a JavaScript environment to operate. The video unit to be measured needs to have a size of at least 30x30 pixels. The DAR Video tag requires access to the VPAID ad unit or to an OM SDK API present in the JavaScript context.<br />
<br />
==== Parameters ====<br />
<br />
The minimum required DAR parameters are '''ca, ci, ce, cr, pc''' and '''am'''. For VPAID wrapper placements, '''vpaidURL''' is also required.<br />
<br />
To comply with MRC guidelines, you will be required to append '''autop''' to indicate click-to-play vs auto-play.<br />
<br />
If the DAR Video tag will act as the VPAID wrapper, '''vpaidURL''' has to be the tag’s last parameter and its value set to the full URL (including parameters) of the original VPAID ad unit.<br />
<br />
See the [[DAR_Tag_Implementation_Guide#Appendix|'''Appendix''']] for a full list of parameters.<br />
<br />
==== Expected Video Ad Session Pings ====<br />
<br />
{| class="wikitable" <br />
! '''Description'''<br />
! '''Timing'''<br />
! '''Path'''<br />
|-<br />
| DAR Main Ping<br />
| At initial load<br />
| secure-gl.imrworldwide.com/cgi-bin/m<br />
|-<br />
| Nielsen Measure Ping<br />
| Measurement start<br />
| events.imrworldwide.com/nmp<br />
|-<br />
| Primary Standard Ping<br />
| After 2 seconds of viewable duration (may not occur based on MRC rules)<br />
| events.imrworldwide.com/psp<br />
|-<br />
| Quarterly Ping<br />
| At 25%, 50%, 75% and 100% of video progress<br />
| events.imrworldwide.com/qp<br />
|-<br />
| Final Ping<br />
| At video stop or window/tab unloading event<br />
| events.imrworldwide.com/fp<br />
|-<br />
| Error Ping<br />
| Potential integration error - please contact your Nielsen representative<br />
| events.imrworldwide.com/er<br />
|}<br />
<br />
==== Ping Flow ====<br />
<br />
This flow illustrates the behavior of the DAR Video tag if the impression pixel is part of the VAST to be sent by the ad player and the JS tag has '''&amp;darsup=1'''. The parameter, <code>darsup=1</code>, is used to suppress the DAR Main Ping from being sent from the JS tag since the DAR main ping will be sent from the DAR impression pixel. This is the default setup if Nielsen’s vWrap tag is being used to set up the video campaign.<br />
<br />
[[File:Screenshot 2022-06-22 2.png]]<br />
{| class="wikitable" <br />
|- <br />
! colspan="2" | Ping Flow Legend<br />
|- <br />
| D0, D1, D2<br />
| Dynamic SIVT Pings at 1, 15 &amp; 30 seconds<br />
|- <br />
| FP<br />
| Final Ping<br />
|- <br />
| IMPID<br />
| Unique Impression ID<br />
|- <br />
| NMP<br />
| Nielsen Main Measure Ping<br />
|-<br />
| PSP<br />
| Primary Standard Ping<br />
|-<br />
| QP<br />
|Quarterly Media Pings at 25%, 50%, 75% and 100%<br />
|-<br />
| SIVT<br />
| Sophisticated Invalid Traffic<br />
|}<br />
<br />
==== Example OMID Video Placement ====<br />
<br />
DAR can be enabled through the OM SDK by passing the required Nielsen OM inputs listed in the table in the VAST &lt;adVerifications&gt; node:<br />
<br />
{| class="wikitable" <br />
! '''OM Parameter'''<br />
! '''Description'''<br />
! '''Nielsen Value'''<br />
! '''Required'''<br />
|-<br />
| Vendor Key<br />
| ID for measurement provider<br />
| nielsen.com-omid<br />
| ✔<br />
|-<br />
| JavaScript Resource URL<br />
| URL for measurement provider’s verification script<br />
| <syntaxhighlight lang="html">https://dar.imrworldwide.com/js/darvideo.js</syntaxhighlight><br />
| ✔<br />
|-<br />
| Verification Parameters<br />
| Measurement provider’s verification tag parameters<br />
| style="font-family:'Courier New', Courier, monospace !important; color:#222222;" |<syntaxhighlight lang="html">ca=nlsnXXXXXX&cr={AD.ID}&ce=publisherXXXX&ci=nlsnciXXXX&<br />
pc=placementID_XXXX1&am=3</syntaxhighlight><br />
| ✔<br />
|-<br />
| Verification Not Executed URL<br />
| Error URL when the ad player denies measurement script execution<br />
| style="font-family:'Courier New', Courier, monospace !important; color:#222222;" | <syntaxhighlight lang="html">https://events.imrworldwide.com/er?ercd=8800&erms=verificationNotExecuted-<br />
{reason}&ca=nlsnXXXXXX&cr=ad_ID_XXXX&ce=publisherXXXX&<br />
ci=nlsnciXXXX&pc=placementID_XXXX5&am=3&c9={devid,Advertising_ID}<br />
&c13={asid,app_id}</syntaxhighlight><br />
|<br />
<br />
|}<br />
<blockquote><br />
Note: The verificationNotExecuted Error URL is recommended for better troubleshooting during campaign setup. If your system can provide a macro for the reason of the interrupted measurement session, it can be added in place of the {reason} placeholder in the error URL. This can be an error code or a clear text error message.<br />
</blockquote><br />
<br />
==== Example VPAID Placement in VAST ====<br />
<br />
A typical VAST placement with VPAID will contain an impression pixel, the DAR Video JS tag as MediaFile of type “VPAID”, and the video MediaFiles will be duplicated as AdParameters object. In the example below, there was no original VPAID ad unit (the original VAST only contained MP4 video files), so the &amp;vpaidURL parameter on the DAR JS tag stays empty.<br />
<br />
In this example, the DAR JavaScript tag will operate as the VPAID ad unit and will play an appropriate media file from the list contained in the AdParameters node.<br />
<br />
<syntaxhighlight lang="json"><br />
...<br />
<Impression id="Nielsen Digital Ad Ratings"><br />
<![CDATA[https://secure-enc.imrworldwide.com/cgi-bin/m?at=view&cy=2&rt=banner&src=njs&<br />
st=image&tpv=vwrap&ca=nlsnXXXXXX&cr={AD.ID}&ce=publisherXXXX&ci=nlsnciXXXX&pc=placementID_XXXX1&am=3]]><br />
</Impression><br />
...<br />
<MediaFiles><br />
<MediaFile apiFramework="VPAID" type="application/javascript"><br />
<![CDATA[https://dar.imrworldwide.com/js/darvideo.js?darsup=1&ca=nlsnXXXXXX&cr={{AD.ID}}&<br />
ce=publisherXXXX&ci=nlsnciXXXX&pc=placementID_XXXX1&am=3]]><br />
</MediaFile><br />
<MediaFile bitrate="720" delivery="progressive" height="480" id="XXXXXX"<br />
maintainAspectRatio="true" scalable="true" type="video/mp4" <br />
width="854"><![CDATA[https://XXXXX.net/XXXXXX.mp4]]><br />
</MediaFile><br />
</MediaFiles><br />
...<br />
<AdParameters><br />
<![CDATA[{"mediaFiles":[{"bitrate":"720","uri":"https://XXXXX.net/XXXXXX.mp4","height":"480","scalable":"true",<br />
"id":"XXXXXX","type":"video/mp4","maintainAspectRatio":"true","delivery":"progressive","width":"854"}]]><br />
</AdParameters><br />
</syntaxhighlight><br />
<br />
==== Server-Side Integration ====<br />
<br />
If you are interested in implementing the DAR tags server-side, e.g. through SSAI, please contact your Nielsen TAM to provide you with the required guidelines.<br />
<br />
==== Notes ====<br />
<br />
Manual placement of the DAR Video tag is only recommended in situations where the DAR vWrap tag can not be utilized, like in certain mobile in-app ad placements or in scenarios where DAR Video needs to be configured as OMID viewability measurement solution.<br />
<br />
== Pixel Tag== <br />
<br />
The DAR Impression pixel provides basic campaign impression counts and allows to cover placements served in environments where the DAR JavaScript tag is not supported.<br />
<br />
=== Environment ===<br />
<br />
The DAR pixel tag should only be used in environments where the DAR JavaScript tag cannot be utilized such as restricted CTV environments, for SSAI Server-Side Beaconing, and other situations where an adequate JavaScript environment is not available.<br />
<br />
=== Parameters ===<br />
<br />
The minimum required DAR parameters are '''ca, ci, ce, cr, pc''', and '''am''' along with fixed valued params, '''at=view''', '''rt=banner''' and '''st=image''' . See the [[DAR_Tag_Implementation_Guide#Appendix|'''Appendix''']] for a full list of parameters.<br />
<br />
=== Example Tag ===<br />
<syntaxhighlight lang="html"><br />
<img src="https://secure-gl.imrworldwide.com/cgi-bin/m?ca=nlsnXXXXXX&cr=crtve<br />
&ce={PUBLISHER.ID}&pc=PLACEMENT.ID}&nlsnciXXXX&am=3&at=view&rt=banner&st=image<br />
&cy=0&r=[timestamp]" style="display:none"/><br />
</syntaxhighlight><br />
<br />
= Tag Integration =<br />
A successful tag integration will require you to go through the following 6 steps.<br />
== Step 1: Determine Your Campaign Needs== <br />
To receive optimal results from DAR measurement, it is good practice to consider the technical requirements of different sites and placements. Please share your media plan with your Technical Account Manager before launch.<br />
<br />
Specifically, be on the lookout for placements that might span across web and mobile ad inventory and make sure if all of the in-app placements support OMID. Also, some placement types may need manual setup and cannot be automated or may need extra time for setup and testing.<br />
<br />
Please reach out to your Nielsen Technical Account Manager (TAM) for advice if the technical requirements for your campaign are not clear.<br />
== Step 2: Generate Tags== <br />
Your Nielsen representative will walk you through the Campaign Management Interface (CMI) so that you can generate DAR tags for your campaigns at any time.<br />
<br />
Nielsen supports macro-based tag generation for several major ad servers. Nielsen’s Technical Account Managers can assist you with any technical questions on tagging campaigns for DAR measurement.<br />
== Step 3: Campaign Integration== <br />
Your Nielsen tags created in CMI will need to be included when you traffic your ad campaigns. Please reach out to your Nielsen TAM for additional guidance and assistance.<br />
== Step 4: Test the Tag Implementation== <br />
Depending on the complexity of the integration, you may be working closely with a TAM at this point or are performing a self-guided tag implementation based on the CMI output.<br />
<br />
If working with a TAM, they will coordinate a plan to test the tag implementation ahead of the campaign go-live date. Depending on your campaign needs, testing will involve either running a diagnostic campaign to validate tagging setup or reviewing test pages or apps.<br />
<br />
In case of a self-guided tag implementation, we recommend to verify and compare the impression counts in the CMI with your planned campaign volume or ad server reports during the first hours of the campaign. If there are any unexpected impression counts, please reach out to your Nielsen TAM.<br />
== Step 5: Share your Ad Server Report== <br />
<br />
=== Why the Ad Server Report is Needed ===<br />
<br />
Knowing the delivered impressions helps Nielsen run Discrepancy Checks ensuring overall quality and reduces errors in the tagging process.<br />
<br />
Nielsen can provide the client with a template with the inputs required to complete the quality checks.<br />
<br />
=== How to Share Your Delivered impressions ===<br />
<br />
Set up an automated daily report from your ad server containing Site Name, Site ID, Placement Name, Placement ID, and data date.<br />
<br />
A secondary method to share your media plan information is to grant Nielsen “Reporting access” to your campaign in the designated ad server (such as DCM). To do this, simply grant the login '''clientreporting@nielsen.com''' access. In doing so Nielsen can directly access your media plan information, which enables us to check for updates, and reconcile any discrepancies.<br />
<br />
== Step 6: Monitoring Your Campaign== <br />
Nielsen recommends all clients participate in Discrepancy Checks. Nielsen’s team will verify that the tags delivered have begun to receive data once the campaign goes live and will regularly (typically every 7-14 days) compare the Nielsen reporting to your 3rd party or publisher reporting to ensure we are capturing all data across all placements, as expected, and that the discrepancy gap between your reporting and the Nielsen reporting is kept to a minimum.<br />
<br />
= Appendix =<br />
== Tag Parameters== <br />
All passthrough parameters will appear on the JavaScript-generated DAR impression ping.<br />
{| class="wikitable" style="background-color:#FFF;"<br />
|- style="font-weight:bold; background-color:#EAECF0; color:#222;"<br />
! Query Parameter<br />
! Description<br />
! style="text-align:center;" | Required<br />
! style="text-align:center;" | Pass-through<br />
|- style="font-weight:bold; text-align:center; vertical-align:middle; background-color:#FFEBD3; color:#222;"<br />
| colspan="4" | Group 1 - Required Parameters<br />
|- style="vertical-align:middle; color:#222;"<br />
| ca<br />
| Campaign ID<br />
| style="text-align:center;" | X<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| pc<br />
| Placement ID<br />
| style="text-align:center;" | X<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| ci<br />
| Client ID<br />
| style="text-align:center;" | X<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| am<br />
| Ad server ID<br />
| style="text-align:center;" | X<br />
| style="text-align:center;" | X<br />
|- style="color:#222;"<br />
| ce<br />
| Site ID<br />
| style="text-align:center;" | X<br />
| style="text-align:center;" | X<br />
|- style="background-color:#F4F5F7; color:#222;"<br />
| cr<br />
| Creative ID<br />
| style="text-align:center; background-color:#EFEFEF;" | X<br />
| style="text-align:center;" | X<br />
|- style="font-weight:bold; text-align:center; vertical-align:middle; background-color:#FFEBD3; color:#222;"<br />
| colspan="4" | Group 2 - Use Case Specific Parameters<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| at<br />
| Fixed Value "view" (Nielsen value, JS tags add this to DAR and NMP pings)<br />
| style="text-align:center;" | Pixel only<br />
| <br />
|- style="vertical-align:middle; color:#222;"<br />
| st<br />
| Fixed Value "image" (Nielsen value, JS tags add this to DAR and NMP pings)<br />
| style="text-align:center;" | Pixel only<br />
| <br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| rt<br />
| Fixed Value "banner" (Nielsen value, JS tags add this to DAR and NMP pings)<br />
| style="text-align:center;" | Pixel only<br />
| <br />
|- style="vertical-align:middle; color:#222;"<br />
| r<br />
| Cachebuster/Timestamp. It's required in the pixel tags with a hardcoded<br />value as a default or a macro (r=timestamp/macro) .<br />
| style="text-align:center;" | Pixel only<br />
| <br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| cy<br />
| Creative type (1: display/2: video) JS tags add this to DAR and NMP pings for In-House Viewability.<br />When parameter is not present or value is missing on pixel tags, there will be no creative type breakout.<br /><br /><br />
| style="text-align:center;" | Pixel only<br />
| <br />
|- style="vertical-align:middle; color:#222;"<br />
| '''[[DAR_Tag_Implementation_Guide#vWrap_apiframework_Values|apiframework]]'''<br />
| IAB-defined value designating the measurement method See vWrap apiframework values<br />
| style="text-align:center;" | vWrap only<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| autof<br />
| Video only: Auto refresh (1 for auto refresh, leave empty otherwise)<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| autop<br />
| Video only: Autoplay (1 for auto-play, 2 for click-to-play, leave empty otherwise)<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| c7<br />
| OS Grouping<br />c7=osgrp,IOS<br />c7=osgrp,DROID<br />c7=osgrp,ANDROID<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| c8<br />
| Device Grouping<br />c8=devgrp,DSK (computers)<br />c8=devgrp,PHN (mobile phone devices)<br />c8=devgrp,TAB (mobile tablet devices)<br />c8=devgrp,PMP (portable media player)<br />c8=devgrp,UNWN (unknown mobile devices)<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| c9<br />
| Mobile Advertising ID<br />c9=devid,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br />
| style="text-align:center;" | Mobile<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| c10<br />
| Platform<br />c10=plt,DSK (Computer)<br />c10=plt,MBL (Mobile)<br />c10=plt,OTT (Connected Device)<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| c12<br />
| App Version<br />c12=apv,xxx<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| c13<br />
| Nielsen Assigned App ID<br />Example:<br />c13=asid,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br />
| style="text-align:center;" | Mobile<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| c14<br />
| OS Version<br />c14=osver,xxx<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| c68<br />
| Mobile App Bundle ID<br />c68=bndlid,xxxxxxxxxxxxxx<br />References:<br />https://developer.apple.com/documentation/appstoreconnectapi/bundle_ids<br />https://developer.android.com/studio/build/configure-app-module#set_the_application_id<br />
| style="text-align:center;" | Mobile<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| C78<br />
| Custom Integration Flag (please note: this is the only uppercase parameter name)<br />
| style="text-align:center;" | some vendors<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| darsup<br />
| If present suppress DAR main ping originating from JS tag (value can be 0 or 1, same effect)<br />
| <br />
| <br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| forceid<br />
| If present provides impid, can be overwritten by impid parameter<br />
| <br />
| style="text-align:center;" | X (as impid)<br />
|- style="vertical-align:middle; color:#222;"<br />
| impid<br />
| Same as forceid, but higher priority in case both are present<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| frcd<br />
| Video only: Forced duration (seconds/null)<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| frcf<br />
| Video only: Forced ad flag (yes/no/null)<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| ptraf<br />
| Video only: Purchased traffic<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| contplay<br />
| Video only: Continuous play<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| gdpr<br />
| GDPR flag to indicate whether GDPR is applicable:<br />0 - GDPR does not apply<br />1 - GDPR applies<br />
| style="text-align:center;" | in some jurisdictions<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| gdpr_consent<br />
| URL-safe base64-encoded Transparency & Consent (TC) string for<br />identifying user's privacy preferences<br />
| style="text-align:center;" | in some jurisdictions<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| hem_sha256<br />
| Hashed email<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| hem_unknown<br />
| Hashed email<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| mode<br />
| VPAID video only, optional: Custom Direct Access mode<br />("w" wrapper / "c" custom; defaults to wrapper)<br />
| <br />
| <br />
|- style="vertical-align:middle; color:#222;"<br />
| onload<br />
| VPAID video only, optional: JS callback for Custom Direct Access VPAID integration<br />
| <br />
| <br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| pub<br />
| Publisher Name<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| pubid<br />
| Publisher ID<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| si<br />
| Site identifier. Canonical URL of the content where the Ad creative is served.<br />The parameter value has to be encoded with encodeURIComponent() method or equivalent.<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| uid2<br />
| Unified ID 2.0<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| uid2_token<br />
| Unified ID 2.0 token<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| uoo<br />
| User opt out<br />
| style="text-align:center;" | Mobile<br />
| style="text-align:center;" | X<br />
|- style="font-weight:bold; text-align:center; vertical-align:middle; background-color:#FFEBD3; color:#222;"<br />
| colspan="4" | Group 3 - Parameters With Required Position in URL<br />
|- style="vertical-align:middle; background-color:#ffffff; color:#222;"<br />
| vpaidURL<br />
| VPAID Video only: Always the last parameter for video tags.<br />Either VPAID ad unit URL to be wrapped or empty. If empty, DAR tag will use its own vpaidplayer.js<br />
| style="text-align:center;" | VPAID video tag only<br />
| <br />
|- style="background-color:#f4f5f7;"<br />
| style="vertical-align:middle; color:#222;" | vastURL<br />
| style="vertical-align:middle; color:#222;" | vWrap Tag only: Always the last parameter for the vWrap tag.<br />It must contain the URL of the original VAST for the placement.<br />
| style="text-align:center; vertical-align:middle; color:#222;" | vWrap tag only<br />
| <br />
|}<br />
<br />
== Additional Parameters == <br />
This section describes several important additional parameters that the DAR tag can support, specifically Hashed Email, UID2 values, along with Page URL and Bundle Identifier if available. Please note that all parameters are case-sensitive.<br />
<br />
Please work with your Nielsen Technical Account Manager to decide which of the following parameters to append to the standard DAR tag.<br />
=== HEM Support (Hashed Email) ===<br />
Please use the parameter that matches your hashing algorithm. For example, if you are using sha256 to encode the email address, then use hem_sha256={encrypted_value_here}<br />
{| class="wikitable" style="font-weight:bold; background-color:#EAECF0;"<br />
|-<br />
! Name<br />
! Description<br />
! Available Tag Parameters<br />
|- style="font-weight:normal; background-color:#F8F9FA;"<br />
| Hashed Email<br />
| User’s email address that has been run through the sha256 hashing algorithm to create a unique hexadecimal string.<br /> If a client is unable to determine hashing type, they should pass<br />using &hem_unknown parameter.<br />
| &hem_unknown<br />&hem_sha256<br /><br />
|}<br />
{| class="wikitable" style="font-weight:bold;"<br />
|- style="background-color:#dae8fc; color:#002041;"<br />
! Example<br />
|- style="font-weight:normal;"<br />
| hem_sha256=671638d17df92ac6e46e3f00ad0e78f09116ca29128e93dcb53ff340abdeb2c2<br />
|}<br />
<br />
=== Unified ID ===<br />
{| class="wikitable" style="background-color:#F8F9FA;"<br />
|- style="font-weight:bold; background-color:#EAECF0;"<br />
! Name<br />
! Description<br />
! Available Tag Parameters<br />
|-<br />
| Unified ID 2.0<br />
| An identifier based on a user’s verifiable PII (e.g. hashed email). UID2.0 was initially created by The Trade Desk (TTD)<br />and is now managed by Prebid.<br />
| &uid2<br />
|-<br />
| Unified ID 2.0 Token<br />
| Encrypted Unified ID 2.0<br />
| &uid_token<br />
|}<br />
{| class="wikitable" style="font-weight:bold;"<br />
|- style="background-color:#32BBB9; color:#002041;"<br />
! Example<br />
|- style="font-weight:normal;"<br />
| uid2=MTKVpUAzwYAPnHrtfE0wlINOMzhU7UUEjjVdCdRu63k=<br />uid_token=AgAAAAPFR0zA5ogv/yaAPiUsAdZPsfqS8QlDSGxAB+rr8yekFs3AjLYVk5qqqiyV2XHbSuwzHmxSlLeQeKQI1mp015jsNnpX5<br />/xGgXldcgVz+gFnyh3T8/3agMwRmyrhCxG4oH2C7fc48AQk2eotE7FW0ZDEYM8fD9ZxDaxFUC/OV3OuZA<br />
|}<br />
<br />
=== Page and Bundle ===<br />
{| class="wikitable" style="background-color:#F8F9FA;"<br />
|- style="font-weight:bold; background-color:#EAECF0;"<br />
! Name<br />
! Description<br />
! Available Tag Parameters<br />
|-<br />
| Page URL<br />
| Canonical URL of the content where the Ad creative is served. (e.g. https://example.com/news/tech/article.html) <br />The parameter value has to be encoded with JavaScript’s encodeURIComponent() method or equivalent. <br />Example: si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
| &si<br />
|-<br />
| App Bundle ID<br />
| The app’s unique bundle ID (e.g. com.example.myapp). The ID can be used to look up the App in Apple’s App Store<br />or the Google Play Store.<br />References: https://developer.android.com/studio/build/application-idhttps://developer.apple.com/documentation/appstoreconnectapi/bundle_ids<br />
| &c68=bndlid<br />
|}<br />
{| class="wikitable" style="font-weight:bold;"<br />
|- style="background-color:#32BBB9; color:#002041;"<br />
! Example<br />
|- style="font-weight:normal;"<br />
| si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />c68=bndlid,com.tam.nielsen.com<br />
|}<br />
<br />
== vWrap apiframework Values== <br />
<br />
Nielsen’s vWrap tag uses the existing definition of '''apiframework''' values defined in the IAB’s [https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/master/AdCOM%20v1.0%20FINAL.md#list--api-frameworks- '''AdCOM Specification''' '''1.0''']. This means that existing macros for this parameter in your system should work out of the box with vWrap.<br />
<br />
The vWrap tag supports the numerical values in bold below. In case of '''8''' (SIMID), the DAR Video tag will be inserted as a standard OMID verification client for viewability measurement and it will not interfere with any SIMID components in the ad.<br />
<br />
If a '''0''' or an empty value is given, the resulting VAST will include both OMID and VPAID measurement solutions. This leaves the decision of the measurement method to the video player, which might be advantageous for mixed campaigns that span mobile and web environments.<br />
<br />
{| class="wikitable" style="font-weight:bold;"<br />
|- style="background-color:#F4F5F7;"<br />
! Value<br />
! Definition<br />
|-<br />
| 1<br />
| style="font-weight:normal;" | VPAID 1.0<br />
|-<br />
| 2<br />
| style="font-weight:normal;" | VPAID 2.0<br />
|- style="font-weight:normal; color:#666;"<br />
| 3<br />
| MRAID 1.0<br />
|- style="font-weight:normal; color:#666;"<br />
| 4<br />
| ORMMA<br />
|- style="font-weight:normal; color:#666;"<br />
| 5<br />
| MRAID 2.0<br />
|- style="font-weight:normal; color:#666;"<br />
| 6<br />
| MRAID 3.0<br />
|-<br />
| 7<br />
| style="font-weight:normal;" | OMID 1.0<br />
|-<br />
| 8<br />
| style="font-weight:normal;" | SIMID 1.0<br />
|}<br />
<br />
== SERVER-SIDE TAG DISPATCH ==<br />
The standard way of triggering a Digital Ad Ratings (DAR) tag on mobile in-app or connected devices is for the publisher to trigger the tag upon ad exposure to the user (either directly or via the ad server). This can be described as a client-side initiated tag.<br />
<br />
It is important to note that MRC/IAB measurement standards stipulate that the ad exposure event still be initiated and recorded from the client-side, even if the ad measurement tag (in this case a DAR tag) is physically initiated from the server-side. Evidence may be required (eg. publisher log file or similar) from the MRC/IAB to substantiate that the user was exposed to the ad on their device.<br />
<br />
In addition to the tag parameters covered in the prior sections, the following HTTP headers need to be modified in the DAR calls to support dispatch from a '''server-side''' publisher ad server:<br />
<br />
{| class="wikitable" <br />
|- style="text-align:center; background-color:#c0c0c0; color:#000000;"<br />
! HTTP Headers<br />
! Description of Modifications<br />
|-<br />
| User-Agent (UA)<br />
| This is expected to be the originating client user-agent for the<br /> device where the user was exposed to the ad. The HTTP UA from <br />the client device should be used to populate the HTTP UA in the<br /> server-side connection/ping. DAR leverages the type of<br />device for platform derivation.<br />
|-<br />
| X-Forwarded-For (XFF) IP<br />
| This is expected to be the originating client IP address for the <br />device where the user was exposed to the ad. Note: When the tag<br /> is fired directly from the ad server, the X-Real-IP will be the ad server IP.<br />
|}<br />
<br />
<br />
=== Server Side Tag Notes ===<br />
<br />
* The server-side tag collection only supports mobile in-app and connected device measurement and will not support cookie-based browser measurement.<br />
<br />
* The client’s server-side setup to trigger/send the DAR tag should suppress any Nielsen cookie returned by the Nielsen collection server as a result of the first DAR tag received. If the Nielsen cookie (returned upon receiving the first DAR tag into secure.imrworldwide.com) is not suppressed, then invalid traffic (IVT) filtration will be triggered upon receiving the 2nd and nth tag.<br />
<br />
* The tag received by Nielsen must be TLS v1.2 compliant or greater.<br />
<br />
== About Nielsen ==<br />
<br />
Nielsen shapes the world’s media and content as a global leader in audience measurement, data and analytics. Through our understanding of people and their behaviors across all channels and platforms, we empower our clients with independent and actionable intelligence so they can connect and engage with their audiences—now and into the future.<br />
<br />
An S&amp;P 500 company, Nielsen (NYSE: NLSN) operates around the world in more than 55 countries. Learn more at [http://www.nielsen.com '''www.nielsen.com'''] or [http://www.nielsen.com/investors '''www.nielsen.com/investors'''] and connect with us on social media.<br />
<br />
'''Audience Is Everything®'''</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DAR_Tag_Implementation_Guide&diff=6386DAR Tag Implementation Guide2023-06-12T18:14:16Z<p>LaMarHolmes: /* Tag Parameters */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
<br />
= Introduction =<br />
<br />
This document provides an overview of the Nielsen Digital Ad Ratings (DAR) Tags and the steps necessary to implement them as part of your digital advertising campaigns.<br />
=== What is DAR ===<br />
DAR is a measurement platform for digital advertising campaigns. The platform provides a clear view of the true audience of a campaign, including Reach, Frequency, and GRP statistics by audience demographic group. <br />
=== What we measure=== <br />
All DAR tags allow you to measure campaign impressions and the DAR JavaScript tags measure ad viewability, GIVT (General Invalid Traffic), and SIVT (Sophisticated Invalid Traffic) across platforms including web, mobile, and in-app.<br />
=== How we measure it=== <br />
Nielsen’s DAR suite of JavaScript tags together with a pixel tag fallback will be present in your ad placements. We utilize industry-standard APIs to perform measurement cross-browser and cross-platform. In most cases, you will only need to add a simple URL through your ad management interface to fully utilize DAR measurement in your campaigns.<br />
=== Prerequisites ===<br />
For steps outlined in this document, you should have access to Nielsen’s Campaign Management Interface (CMI) and a Nielsen Technical Account Manager (TAM) will be working with you during the implementation phase.<br />
__TOC__<br />
= DAR Measurement Types =<br />
<br />
== DAR Display== <br />
<br />
The DAR Display JavaScript tag reports ad impressions as well as measures ad viewability and SIVT. In standard web placements, it will find the ad unit in the surrounding DOM container and will then report viewability as a time series with a 1-second resolution.<br />
<br />
The DAR tag will report the MRC-required minimum of 1 second on screen and a continuous viewability time series for the lifetime of the ad session to enable additional viewability qualifiers.<br />
<br />
The tag can utilize the IAB’s [https://iabtechlab.com/standards/open-measurement-sdk/ '''Open Measurement SDK'''] (OM SDK) including [https://iabtechlab.com/blog/open-measurement-for-web-video-arrives/ '''OM Web'''] integration if the OM Interface Definition (OMID) is available, or it will use industry-standard web APIs to measure viewability.<br />
<br />
=== Requirements ===<br />
<br />
The DAR Display tag requires a JavaScript-enabled browser for web environments or the OM SDK for in-app to operate and should be placed close to the corresponding measured ad unit. It should be on the same DOM level (e.g. directly under the same parent) or in a child node under the same parent node. The ad unit should be a content-bearing DOM element (e.g. img, canvas, SVG, iframe, div) with a minimum size of 30x30 pixels.<br />
<br />
=== Parameters ===<br />
<br />
The minimum required DAR parameters are '''ca, ci, cr, pc, ce''' and '''am'''. See the [[DAR_Tag_Implementation_Guide#Appendix|'''Appendix''']] for a full list of parameters.<br />
<br />
=== Example Tag ===<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript" <br />
src="https://dar.imrworldwide.com/js/dar.js?ca=nlsnXXXXXX&cr={AD.ID}&ce={PUBLISHER.ID}&ci=nlsnciXXXX&pc={PLACEMENT.ID}&am=3"><br />
</script><br />
</syntaxhighlight><br />
<br />
=== Example OMID Display Placement ===<br />
<br />
DAR can be enabled through the OM SDK by passing the required Nielsen OM inputs listed in the table below during setup:<br />
<br />
{| class="wikitable" <br />
|-<br />
! style="width: 20%" | OM Parameter<br />
! style="width: 40%" | Description<br />
! style="width: 40%" | Nielsen Value<br />
! style="width: 5%" |Required<br />
|-<br />
| Vendor Key<br />
| ID for measurement provider<br />
| nielsen.com-omid<br />
| ✔<br />
|-<br />
| JavaScript Resource URL<br />
| URL for measurement provider’s verification script<br />
|<syntaxhighlight lang="html"> https://dar.imrworldwide.com/js/dar.js</syntaxhighlight><br />
| ✔<br />
|-<br />
| Verification Parameters<br />
| Measurement provider’s verification tag parameters<br />
| style="font-family:'Courier New', Courier, monospace !important; color:#222222;" |<syntaxhighlight lang="html">ca=nlsnXXXXXX&cr={AD.ID}&ce=publisherXXXX&ci=nlsnciXXXX&pc=placementID_XXXX1&am=3</syntaxhighlight><br />
| ✔<br />
|-<br />
| Verification Not Executed URL<br />
| Error URL when the ad player denies measurement script execution<br />
| style="font-family:'Courier New', Courier, monospace !important; color:#222222;" | <syntaxhighlight lang="html">https://events.imrworldwide.com/er?ercd=8800&erms=verificationNotExecuted-<br />
{reason}&ca=nlsnXXXXXX&cr=ad_ID_XXXX&ce=publisherXXXX&<br />
ci=nlsnciXXXX&pc=placementID_XXXX5&am=3<br />
&c13={asid,app_id}</syntaxhighlight><br />
|<br />
<br />
|}<br />
<br />
<blockquote><br />
Note: The verificationNotExecuted Error URL is recommended for better troubleshooting during campaign setup. If your system can provide a macro for the reason of the interrupted measurement session, it can be added in place of the {reason} placeholder in the error URL. This can be an error code or a clear text error message.</blockquote><br />
<br />
=== Expected Display Ad Session Pings ===<br />
{| class="wikitable" <br />
<br />
! '''Description'''<br />
! '''Timing'''<br />
! '''Path'''<br />
|-<br />
| DAR Main Ping<br />
| At initial load<br />
| secure-gl.imrworldwide.com/cgi-bin/m<br />
|-<br />
| Nielsen Measure Ping<br />
| Measurement start<br />
| events.imrworldwide.com/nmp<br />
|-<br />
| Primary Standard Ping<br />
| After 1 second of viewable duration (may not occur based on MRC rules)<br />
| events.imrworldwide.com/psp<br />
|-<br />
| Timed Pings<br />
| At 1, 5, 15 and 120 seconds of ad session time (may not occur based on ad session length)<br />
| events.imrworldwide.com/1sp, 5sp, 15sp, 120sp<br />
|-<br />
| Final Ping<br />
| At window/tab unloading event<br />
| events.imrworldwide.com/fp<br />
|-<br />
| Error Ping<br />
| Potential integration error - please contact your Nielsen representative<br />
| events.imrworldwide.com/er<br />
|}<br />
<br />
=== Ping Flow ===<br />
<br />
This flow illustrates the behavior of the DAR Display tag.<br /><br />
<br />
[[File:Screenshot 2022-06-22 152646.png]]<br />
<br />
{| class="wikitable" <br />
|- <br />
! colspan="2" | Ping Flow Legend<br />
|- <br />
| 1SP, 5SP, 15SP, 120SP<br />
| Timed Measure Ping at 1, 5, 15 and 120 seconds<br />
|- <br />
| D0, D1, D2<br />
| Dynamic SIVT Pings at 1, 15 &amp; 30 seconds<br />
|- <br />
| FP<br />
| Final Ping<br />
|- <br />
| IMPID<br />
| Unique Impression ID<br />
|- <br />
| NMP<br />
| Nielsen Main Measure Ping<br />
|-<br />
| PSP<br />
| Primary Standard Ping<br />
|-<br />
| SIVT<br />
| Sophisticated Invalid Traffic<br />
|}<br />
<br />
== DAR Video == <br />
<br />
The DAR Video tag will typically be trafficked as part of a Video Ad Serving Template (VAST) file. Nielsen provides its wrapped video tag (vWrap) to make this type of deployment easy and consistent across the various ad servers and trafficking options. Nielsen’s vWrap tag supports both automatic OMID and VPAID integration with existing VAST files. The two sections below, [[#Wrapped_Video_Tag_.28vWrap.29_Deployment|'''Wrapped Video Tag''']] and [[#Video_JS_Tag|'''Video JS Tag''']], describe these options and their expected outcomes.<br />
<br />
In addition, Nielsen supports '''direct DAR Video tag deployments''' with manual integration in existing workflows. In this case, the section [[#video-js-tag|'''Video JS Tag''']] below describes the basic setup and expected results. In addition, it is recommended that you work closely with your Nielsen Technical Account Manager if you consider a manual tag integration with your campaigns.<br />
<br />
=== Wrapped Video Tag (vWrap) Deployment ===<br />
<br />
Nielsen’s wrapped DAR video tag, vWrap, is the preferred delivery method for VAST-controlled video ad placements.The vWrap tag is served by a Nielsen service that takes an original VAST with an inline ad (not a wrapper redirect) and dynamically adds the DAR Video tag with measurement solutions for VPAID and OMID. The '''apiframework''' parameter can be used to control which measurement solution will be inserted (see below).<br />
<br />
=== Parameters ===<br />
<br />
The minimum required DAR parameters are '''ca, ci, ce, cr, pc''', '''am, apiframework''' and '''vastURL'''. See the [[DAR_Tag_Implementation_Guide#Appendix|'''Appendix''']] for a full list of parameters.<br />
<br />
The Open Real Time Bidding ([https://iabtechlab.com/wp-content/uploads/2022/04/OpenRTB-2-6_FINAL.pdf '''OpenRTB''']) API framework values for identifying the ad inventory type should be passed in the Nielsen '''apiframework''' parameter. The values should be either 1 or 2 (VPAID) or 7 or 8 (OMID). The available API framework values are listed in the IAB’s [https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/master/AdCOM%20v1.0%20FINAL.md#list--api-frameworks- '''AdCOM specification 1.0''']. If the parameter is left blank or set to 0, Wrap will add the DAR Video tag as '''both''' an OMID verification client and VPAID wrapper. See more details in the [[DAR_Tag_Implementation_Guide#Appendix|'''Appendix''']].<br />
<br />
The '''vastURL''' parameter must be the last parameter on the DAR tag with its value set as the full URL (including all original parameters) of the original VAST tag for the ad placement.<br />
<br />
=== Example Wrapped Video Tag (vWrap) ===<br />
{| class="wikitable" style="font-family:'Courier New', Courier, monospace !important;"<br />
|-<br />
! <syntaxhighlight lang="html"> https://vwrap.imrworldwide.com/v1/wrap?ca=nlsnXXXXXX&cr={AD.ID}&ce={PUBLISHER.ID}&pc={PLACEMENT.ID}&ci=nlsnciXXXX&am=4&<br />
c9={devid,Advertising_ID}&c13=asid,app_id}&apiframework={APIFRAMEWORK}&vastURL={ORIGINAL_VAST_URL}</syntaxhighlight><br />
|}<br />
<blockquote><br />
To observe how vWrap operates, we have provided some example VAST URLs which you can load directly in your browser.<br />
</blockquote><br />
==== VAST ad Unit, no Impression/Viewability ====<br />
First, here is a VAST ad unit with a single video file and no impression tracking or viewability measurement:<br />
{| class="wikitable" <br />
|-<br />
! https://madimator.com/vast-examples/example_video_only_nielsen_15s.xml <br />
|}<br />
==== VAST ad Unit, Nielsen vWrap for OMID measurement ====<br />
This is the same VAST file loaded via Nielsen’s vWrap tag for '''OMID measurement''' (apiframework is set to 7):<br />
{| class="wikitable" <br />
|-<br />
! https://vwrap.imrworldwide.com/v1/wrap?ca=nlsn305255&cr=nielsenomidtest&ce=nielsen&pc=vastomid&ci=nlsntest&am=4&apiframework=7&vastURL=http://madimator.com/vast-examples/example_video_only_nielsen_15s.xml<br />
|}<br />
<br />
==== VAST ad Unit, Nielsen vWrap for VPAID measurement ====<br />
And here is the same VAST with the vWrap tag configured for '''VPAID measurement''' (apiframework is set to 2):<br />
{| class="wikitable" <br />
|-<br />
!https://vwrap.imrworldwide.com/v1/wrap?ca=nlsn305255&cr=nielsenomidtest&ce=nielsen&pc=vastvpaid&ci=nlsntest&am=4&apiframework=2&vastURL=http://madimator.com/vast-examples/example_video_only_nielsen_15s.xml <br />
|}<br />
<br />
=== Video JS Tag ===<br />
<br />
The DAR Video tag supports both OM SDK and VPAID video ad measurement and provides viewability time series, audio volume time series, GIVT, and SIVT data. The time series contains playhead events with corresponding measurements at a 1-second resolution. In addition to the time series, a dedicated ping will report on the MRC-required minimum of 2 seconds on screen.<br />
<br />
With OM SDK, the DAR Video tag supports the following ad types:<br />
<br />
* Native mobile in-app ad placements <br />
* Mobile web ads<br />
* OM Web placements<br />
* OMID-enabled streaming video players with ad SDKs (for instance DAI IMA SDK)<br />
<br />
<br />
With VPAID, it supports the following operating modes:<br />
* As VPAID wrapper for an existing VPAID ad unit in the VAST<br />
* As VPAID ad unit in a VAST with video files and AdParameters node<br />
* In Custom Integrations with VPAID host players<br />
<br />
<br />
<br />
In most cases, the DAR Video tag should not be manually implemented as a wrapper, instead consider utilizing Nielsen’s vWrap tag.<br />
<br />
==== Requirements ====<br />
<br />
The DAR Video tag needs a JavaScript environment to operate. The video unit to be measured needs to have a size of at least 30x30 pixels. The DAR Video tag requires access to the VPAID ad unit or to an OM SDK API present in the JavaScript context.<br />
<br />
==== Parameters ====<br />
<br />
The minimum required DAR parameters are '''ca, ci, ce, cr, pc''' and '''am'''. For VPAID wrapper placements, '''vpaidURL''' is also required.<br />
<br />
To comply with MRC guidelines, you will be required to append '''autop''' to indicate click-to-play vs auto-play.<br />
<br />
If the DAR Video tag will act as the VPAID wrapper, '''vpaidURL''' has to be the tag’s last parameter and its value set to the full URL (including parameters) of the original VPAID ad unit.<br />
<br />
See the [[DAR_Tag_Implementation_Guide#Appendix|'''Appendix''']] for a full list of parameters.<br />
<br />
==== Expected Video Ad Session Pings ====<br />
<br />
{| class="wikitable" <br />
! '''Description'''<br />
! '''Timing'''<br />
! '''Path'''<br />
|-<br />
| DAR Main Ping<br />
| At initial load<br />
| secure-gl.imrworldwide.com/cgi-bin/m<br />
|-<br />
| Nielsen Measure Ping<br />
| Measurement start<br />
| events.imrworldwide.com/nmp<br />
|-<br />
| Primary Standard Ping<br />
| After 2 seconds of viewable duration (may not occur based on MRC rules)<br />
| events.imrworldwide.com/psp<br />
|-<br />
| Quarterly Ping<br />
| At 25%, 50%, 75% and 100% of video progress<br />
| events.imrworldwide.com/qp<br />
|-<br />
| Final Ping<br />
| At video stop or window/tab unloading event<br />
| events.imrworldwide.com/fp<br />
|-<br />
| Error Ping<br />
| Potential integration error - please contact your Nielsen representative<br />
| events.imrworldwide.com/er<br />
|}<br />
<br />
==== Ping Flow ====<br />
<br />
This flow illustrates the behavior of the DAR Video tag if the impression pixel is part of the VAST to be sent by the ad player and the JS tag has '''&amp;darsup=1'''. The parameter, <code>darsup=1</code>, is used to suppress the DAR Main Ping from being sent from the JS tag since the DAR main ping will be sent from the DAR impression pixel. This is the default setup if Nielsen’s vWrap tag is being used to set up the video campaign.<br />
<br />
[[File:Screenshot 2022-06-22 2.png]]<br />
{| class="wikitable" <br />
|- <br />
! colspan="2" | Ping Flow Legend<br />
|- <br />
| D0, D1, D2<br />
| Dynamic SIVT Pings at 1, 15 &amp; 30 seconds<br />
|- <br />
| FP<br />
| Final Ping<br />
|- <br />
| IMPID<br />
| Unique Impression ID<br />
|- <br />
| NMP<br />
| Nielsen Main Measure Ping<br />
|-<br />
| PSP<br />
| Primary Standard Ping<br />
|-<br />
| QP<br />
|Quarterly Media Pings at 25%, 50%, 75% and 100%<br />
|-<br />
| SIVT<br />
| Sophisticated Invalid Traffic<br />
|}<br />
<br />
==== Example OMID Video Placement ====<br />
<br />
DAR can be enabled through the OM SDK by passing the required Nielsen OM inputs listed in the table in the VAST &lt;adVerifications&gt; node:<br />
<br />
{| class="wikitable" <br />
! '''OM Parameter'''<br />
! '''Description'''<br />
! '''Nielsen Value'''<br />
! '''Required'''<br />
|-<br />
| Vendor Key<br />
| ID for measurement provider<br />
| nielsen.com-omid<br />
| ✔<br />
|-<br />
| JavaScript Resource URL<br />
| URL for measurement provider’s verification script<br />
| <syntaxhighlight lang="html">https://dar.imrworldwide.com/js/darvideo.js</syntaxhighlight><br />
| ✔<br />
|-<br />
| Verification Parameters<br />
| Measurement provider’s verification tag parameters<br />
| style="font-family:'Courier New', Courier, monospace !important; color:#222222;" |<syntaxhighlight lang="html">ca=nlsnXXXXXX&cr={AD.ID}&ce=publisherXXXX&ci=nlsnciXXXX&<br />
pc=placementID_XXXX1&am=3</syntaxhighlight><br />
| ✔<br />
|-<br />
| Verification Not Executed URL<br />
| Error URL when the ad player denies measurement script execution<br />
| style="font-family:'Courier New', Courier, monospace !important; color:#222222;" | <syntaxhighlight lang="html">https://events.imrworldwide.com/er?ercd=8800&erms=verificationNotExecuted-<br />
{reason}&ca=nlsnXXXXXX&cr=ad_ID_XXXX&ce=publisherXXXX&<br />
ci=nlsnciXXXX&pc=placementID_XXXX5&am=3&c9={devid,Advertising_ID}<br />
&c13={asid,app_id}</syntaxhighlight><br />
|<br />
<br />
|}<br />
<blockquote><br />
Note: The verificationNotExecuted Error URL is recommended for better troubleshooting during campaign setup. If your system can provide a macro for the reason of the interrupted measurement session, it can be added in place of the {reason} placeholder in the error URL. This can be an error code or a clear text error message.<br />
</blockquote><br />
<br />
==== Example VPAID Placement in VAST ====<br />
<br />
A typical VAST placement with VPAID will contain an impression pixel, the DAR Video JS tag as MediaFile of type “VPAID”, and the video MediaFiles will be duplicated as AdParameters object. In the example below, there was no original VPAID ad unit (the original VAST only contained MP4 video files), so the &amp;vpaidURL parameter on the DAR JS tag stays empty.<br />
<br />
In this example, the DAR JavaScript tag will operate as the VPAID ad unit and will play an appropriate media file from the list contained in the AdParameters node.<br />
<br />
<syntaxhighlight lang="json"><br />
...<br />
<Impression id="Nielsen Digital Ad Ratings"><br />
<![CDATA[https://secure-enc.imrworldwide.com/cgi-bin/m?at=view&cy=2&rt=banner&src=njs&<br />
st=image&tpv=vwrap&ca=nlsnXXXXXX&cr={AD.ID}&ce=publisherXXXX&ci=nlsnciXXXX&pc=placementID_XXXX1&am=3]]><br />
</Impression><br />
...<br />
<MediaFiles><br />
<MediaFile apiFramework="VPAID" type="application/javascript"><br />
<![CDATA[https://dar.imrworldwide.com/js/darvideo.js?darsup=1&ca=nlsnXXXXXX&cr={{AD.ID}}&<br />
ce=publisherXXXX&ci=nlsnciXXXX&pc=placementID_XXXX1&am=3]]><br />
</MediaFile><br />
<MediaFile bitrate="720" delivery="progressive" height="480" id="XXXXXX"<br />
maintainAspectRatio="true" scalable="true" type="video/mp4" <br />
width="854"><![CDATA[https://XXXXX.net/XXXXXX.mp4]]><br />
</MediaFile><br />
</MediaFiles><br />
...<br />
<AdParameters><br />
<![CDATA[{"mediaFiles":[{"bitrate":"720","uri":"https://XXXXX.net/XXXXXX.mp4","height":"480","scalable":"true",<br />
"id":"XXXXXX","type":"video/mp4","maintainAspectRatio":"true","delivery":"progressive","width":"854"}]]><br />
</AdParameters><br />
</syntaxhighlight><br />
<br />
==== Server-Side Integration ====<br />
<br />
If you are interested in implementing the DAR tags server-side, e.g. through SSAI, please contact your Nielsen TAM to provide you with the required guidelines.<br />
<br />
==== Notes ====<br />
<br />
Manual placement of the DAR Video tag is only recommended in situations where the DAR vWrap tag can not be utilized, like in certain mobile in-app ad placements or in scenarios where DAR Video needs to be configured as OMID viewability measurement solution.<br />
<br />
== Pixel Tag== <br />
<br />
The DAR Impression pixel provides basic campaign impression counts and allows to cover placements served in environments where the DAR JavaScript tag is not supported.<br />
<br />
=== Environment ===<br />
<br />
The DAR pixel tag should only be used in environments where the DAR JavaScript tag cannot be utilized such as restricted CTV environments, for SSAI Server-Side Beaconing, and other situations where an adequate JavaScript environment is not available.<br />
<br />
=== Parameters ===<br />
<br />
The minimum required DAR parameters are '''ca, ci, ce, cr, pc''', and '''am''' along with fixed valued params, '''at=view''', '''rt=banner''' and '''st=image''' . See the [[DAR_Tag_Implementation_Guide#Appendix|'''Appendix''']] for a full list of parameters.<br />
<br />
=== Example Tag ===<br />
<syntaxhighlight lang="html"><br />
<img src="https://secure-gl.imrworldwide.com/cgi-bin/m?ca=nlsnXXXXXX&cr=crtve<br />
&ce={PUBLISHER.ID}&pc=PLACEMENT.ID}&nlsnciXXXX&am=3&at=view&rt=banner&st=image<br />
&cy=0&r=[timestamp]" style="display:none"/><br />
</syntaxhighlight><br />
<br />
= Tag Integration =<br />
A successful tag integration will require you to go through the following 6 steps.<br />
== Step 1: Determine Your Campaign Needs== <br />
To receive optimal results from DAR measurement, it is good practice to consider the technical requirements of different sites and placements. Please share your media plan with your Technical Account Manager before launch.<br />
<br />
Specifically, be on the lookout for placements that might span across web and mobile ad inventory and make sure if all of the in-app placements support OMID. Also, some placement types may need manual setup and cannot be automated or may need extra time for setup and testing.<br />
<br />
Please reach out to your Nielsen Technical Account Manager (TAM) for advice if the technical requirements for your campaign are not clear.<br />
== Step 2: Generate Tags== <br />
Your Nielsen representative will walk you through the Campaign Management Interface (CMI) so that you can generate DAR tags for your campaigns at any time.<br />
<br />
Nielsen supports macro-based tag generation for several major ad servers. Nielsen’s Technical Account Managers can assist you with any technical questions on tagging campaigns for DAR measurement.<br />
== Step 3: Campaign Integration== <br />
Your Nielsen tags created in CMI will need to be included when you traffic your ad campaigns. Please reach out to your Nielsen TAM for additional guidance and assistance.<br />
== Step 4: Test the Tag Implementation== <br />
Depending on the complexity of the integration, you may be working closely with a TAM at this point or are performing a self-guided tag implementation based on the CMI output.<br />
<br />
If working with a TAM, they will coordinate a plan to test the tag implementation ahead of the campaign go-live date. Depending on your campaign needs, testing will involve either running a diagnostic campaign to validate tagging setup or reviewing test pages or apps.<br />
<br />
In case of a self-guided tag implementation, we recommend to verify and compare the impression counts in the CMI with your planned campaign volume or ad server reports during the first hours of the campaign. If there are any unexpected impression counts, please reach out to your Nielsen TAM.<br />
== Step 5: Share your Ad Server Report== <br />
<br />
=== Why the Ad Server Report is Needed ===<br />
<br />
Knowing the delivered impressions helps Nielsen run Discrepancy Checks ensuring overall quality and reduces errors in the tagging process.<br />
<br />
Nielsen can provide the client with a template with the inputs required to complete the quality checks.<br />
<br />
=== How to Share Your Delivered impressions ===<br />
<br />
Set up an automated daily report from your ad server containing Site Name, Site ID, Placement Name, Placement ID, and data date.<br />
<br />
A secondary method to share your media plan information is to grant Nielsen “Reporting access” to your campaign in the designated ad server (such as DCM). To do this, simply grant the login '''clientreporting@nielsen.com''' access. In doing so Nielsen can directly access your media plan information, which enables us to check for updates, and reconcile any discrepancies.<br />
<br />
== Step 6: Monitoring Your Campaign== <br />
Nielsen recommends all clients participate in Discrepancy Checks. Nielsen’s team will verify that the tags delivered have begun to receive data once the campaign goes live and will regularly (typically every 7-14 days) compare the Nielsen reporting to your 3rd party or publisher reporting to ensure we are capturing all data across all placements, as expected, and that the discrepancy gap between your reporting and the Nielsen reporting is kept to a minimum.<br />
<br />
= Appendix =<br />
== Tag Parameters== <br />
All passthrough parameters will appear on the JavaScript-generated DAR impression ping.<br />
{| class="wikitable" style="background-color:#FFF;"<br />
|- style="font-weight:bold; background-color:#EAECF0; color:#222;"<br />
! Query Parameter<br />
! Description<br />
! style="text-align:center;" | Required<br />
! style="text-align:center;" | Pass-through<br />
|- style="font-weight:bold; text-align:center; vertical-align:middle; background-color:#FFEBD3; color:#222;"<br />
| colspan="4" | Group 1 - Required Parameters<br />
|- style="vertical-align:middle; color:#222;"<br />
| ca<br />
| Campaign ID<br />
| style="text-align:center;" | X<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| pc<br />
| Placement ID<br />
| style="text-align:center;" | X<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| ci<br />
| Client ID<br />
| style="text-align:center;" | X<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| am<br />
| Ad server ID<br />
| style="text-align:center;" | X<br />
| style="text-align:center;" | X<br />
|- style="color:#222;"<br />
| ce<br />
| Site ID<br />
| style="text-align:center;" | X<br />
| style="text-align:center;" | X<br />
|- style="background-color:#F4F5F7; color:#222;"<br />
| cr<br />
| Creative ID<br />
| style="text-align:center; background-color:#EFEFEF;" | X<br />
| style="text-align:center;" | X<br />
|- style="font-weight:bold; text-align:center; vertical-align:middle; background-color:#FFEBD3; color:#222;"<br />
| colspan="4" | Group 2 - Use Case Specific Parameters<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| at<br />
| Fixed Value "view" (Nielsen value, JS tags add this to DAR and NMP pings)<br />
| style="text-align:center;" | Pixel only<br />
| <br />
|- style="vertical-align:middle; color:#222;"<br />
| st<br />
| Fixed Value "image" (Nielsen value, JS tags add this to DAR and NMP pings)<br />
| style="text-align:center;" | Pixel only<br />
| <br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| rt<br />
| Fixed Value "banner" (Nielsen value, JS tags add this to DAR and NMP pings)<br />
| style="text-align:center;" | Pixel only<br />
| <br />
|- style="vertical-align:middle; color:#222;"<br />
| r<br />
| Cachebuster/Timestamp. It's required in the pixel tags with a hardcoded<br />value as a default or a macro (r=timestamp/macro) .<br />
| style="text-align:center;" | Pixel only<br />
| <br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| cy<br />
| Creative type (1: display/2: video) JS tags add this to DAR and NMP pings for In-House Viewability.<br />When parameter is not present or value is missing on pixel tags, there will be no creative type breakout.<br /><br /><br />
| style="text-align:center;" | Pixel only<br />
| <br />
|- style="vertical-align:middle; color:#222;"<br />
| '''[[DAR_Tag_Implementation_Guide#vWrap_apiframework_Values|apiframework]]'''<br />
| IAB-defined value designating the measurement method See vWrap apiframework values<br />
| style="text-align:center;" | vWrap only<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| autof<br />
| Video only: Auto refresh (1 for auto refresh, leave empty otherwise)<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| autop<br />
| Video only: Autoplay (1 for auto-play, 2 for click-to-play, leave empty otherwise)<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| c7<br />
| OS Grouping<br />c7=osgrp,IOS<br />c7=osgrp,DROID<br />c7=osgrp,ANDROID<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| c8<br />
| Device Grouping<br />c8=devgrp,DSK (computers)<br />c8=devgrp,PHN (mobile phone devices)<br />c8=devgrp,TAB (mobile tablet devices)<br />c8=devgrp,PMP (portable media player)<br />c8=devgrp,UNWN (unknown mobile devices)<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| c9<br />
| Mobile Advertising ID<br />c9=devid,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br />
| style="text-align:center;" | Mobile<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| c10<br />
| Platform<br />c10=plt,DSK (Computer)<br />c10=plt,MBL (Mobile)<br />c10=plt,OTT (Connected Device)<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| c12<br />
| App Version<br />c12=apv,xxx<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| c13<br />
| Nielsen Assigned App ID<br />Example:<br />c13=asid,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx<br />
| style="text-align:center;" | Mobile<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| c14<br />
| OS Version<br />c14=osver,xxx<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| c68<br />
| Mobile App Bundle ID<br />c68=bndlid,xxxxxxxxxxxxxx<br />References:<br />https://developer.apple.com/documentation/appstoreconnectapi/bundle_ids<br />https://developer.android.com/studio/build/configure-app-module#set_the_application_id<br />
| style="text-align:center;" | Mobile<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| C78<br />
| Custom Integration Flag (please note: this is the only uppercase parameter name)<br />
| style="text-align:center;" | some vendors<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| darsup<br />
| If present suppress DAR main ping originating from JS tag (value can be 0 or 1, same effect)<br />
| <br />
| <br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| forceid<br />
| If present provides impid, can be overwritten by impid parameter<br />
| <br />
| style="text-align:center;" | X (as impid)<br />
|- style="vertical-align:middle; color:#222;"<br />
| impid<br />
| Same as forceid, but higher priority in case both are present<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| frcd<br />
| Video only: Forced duration (seconds/null)<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| frcf<br />
| Video only: Forced ad flag (yes/no/null)<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| ptraf<br />
| Video only: Purchased traffic<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| contplay<br />
| Video only: Continuous play<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| gdpr<br />
| GDPR flag to indicate whether GDPR is applicable:<br />0 - GDPR does not apply<br />1 - GDPR applies<br />
| style="text-align:center;" | in some jurisdictions<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| gdpr_consent<br />
| URL-safe base64-encoded Transparency & Consent (TC) string for<br />identifying user's privacy preferences<br />
| style="text-align:center;" | in some jurisdictions<br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| hem_sha256<br />
| Hashed email<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| hem_unknown<br />
| Hashed email<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| mode<br />
| VPAID video only, optional: Custom Direct Access mode<br />("w" wrapper / "c" custom; defaults to wrapper)<br />
| <br />
| <br />
|- style="vertical-align:middle; color:#222;"<br />
| onload<br />
| VPAID video only, optional: JS callback for Custom Direct Access VPAID integration<br />
| <br />
| <br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| pub<br />
| Publisher Name<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| pubid<br />
| Publisher ID<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| si<br />
| Site identifier. Canonical URL of the content where the Ad creative is served.<br />The parameter value has to be encoded with encodeURIComponent() method or equivalent.<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| uid2<br />
| Unified ID 2.0<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; background-color:#EFEFEF; color:#222;"<br />
| uid2_token<br />
| Unified ID 2.0 token<br />
| <br />
| style="text-align:center;" | X<br />
|- style="vertical-align:middle; color:#222;"<br />
| uoo<br />
| User opt out<br />
| style="text-align:center;" | Mobile<br />
| style="text-align:center;" | X<br />
|- style="font-weight:bold; text-align:center; vertical-align:middle; background-color:#FFEBD3; color:#222;"<br />
| colspan="4" | Group 3 - Parameters With Required Position in URL<br />
|- style="vertical-align:middle; background-color:#ffffff; color:#222;"<br />
| vpaidURL<br />
| VPAID Video only: Always the last parameter for video tags.<br />Either VPAID ad unit URL to be wrapped or empty. If empty, DAR tag will use its own vpaidplayer.js<br />
| style="text-align:center;" | VPAID video tag only<br />
| <br />
|- style="background-color:#f4f5f7;"<br />
| style="vertical-align:middle; color:#222;" | vastURL<br />
| style="vertical-align:middle; color:#222;" | vWrap Tag only: Always the last parameter for the vWrap tag.<br />It must contain the URL of the original VAST for the placement.<br />
| style="text-align:center; vertical-align:middle; color:#222;" | vWrap tag only<br />
| <br />
|}<br />
<br />
== Additional Parameters == <br />
This section describes several important additional parameters that the DAR tag can support, specifically Hashed Email, UID2 values, along with Page URL and Bundle Identifier if available. Please note that all parameters are case-sensitive.<br />
<br />
Please work with your Nielsen Technical Account Manager to decide which of the following parameters to append to the standard DAR tag.<br />
=== HEM Support (Hashed Email) ===<br />
Please use the parameter that matches your hashing algorithm. For example, if you are using sha256 to encode the email address, then use hem_sha256={encrypted_value_here}<br />
{| class="wikitable" style="font-weight:bold; background-color:#EAECF0;"<br />
|-<br />
! Name<br />
! Description<br />
! Available Tag Parameters<br />
|- style="font-weight:normal; background-color:#F8F9FA;"<br />
| Hashed Email<br />
| User’s email address that has been run through a hashing algorithm<br />(e.g. SHA256, MD5, SHA1) to create a unique hexadecimal string.<br /> If a client is unable to determine hashing type, they should pass<br />using &hem_unknown parameter.<br />
| &hem_unknown<br />&hem_sha256<br />&hem_md5<br />&hem_sha1<br />
|}<br />
{| class="wikitable" style="font-weight:bold;"<br />
|- style="background-color:#dae8fc; color:#002041;"<br />
! Example<br />
|- style="font-weight:normal;"<br />
| hem_sha256=671638d17df92ac6e46e3f00ad0e78f09116ca29128e93dcb53ff340abdeb2c2<br />
|}<br />
<br />
=== Unified ID ===<br />
{| class="wikitable" style="background-color:#F8F9FA;"<br />
|- style="font-weight:bold; background-color:#EAECF0;"<br />
! Name<br />
! Description<br />
! Available Tag Parameters<br />
|-<br />
| Unified ID 2.0<br />
| An identifier based on a user’s verifiable PII (e.g. hashed email). UID2.0 was initially created by The Trade Desk (TTD)<br />and is now managed by Prebid.<br />
| &uid2<br />
|-<br />
| Unified ID 2.0 Token<br />
| Encrypted Unified ID 2.0<br />
| &uid_token<br />
|}<br />
{| class="wikitable" style="font-weight:bold;"<br />
|- style="background-color:#32BBB9; color:#002041;"<br />
! Example<br />
|- style="font-weight:normal;"<br />
| uid2=MTKVpUAzwYAPnHrtfE0wlINOMzhU7UUEjjVdCdRu63k=<br />uid_token=AgAAAAPFR0zA5ogv/yaAPiUsAdZPsfqS8QlDSGxAB+rr8yekFs3AjLYVk5qqqiyV2XHbSuwzHmxSlLeQeKQI1mp015jsNnpX5<br />/xGgXldcgVz+gFnyh3T8/3agMwRmyrhCxG4oH2C7fc48AQk2eotE7FW0ZDEYM8fD9ZxDaxFUC/OV3OuZA<br />
|}<br />
<br />
=== Page and Bundle ===<br />
{| class="wikitable" style="background-color:#F8F9FA;"<br />
|- style="font-weight:bold; background-color:#EAECF0;"<br />
! Name<br />
! Description<br />
! Available Tag Parameters<br />
|-<br />
| Page URL<br />
| Canonical URL of the content where the Ad creative is served. (e.g. https://example.com/news/tech/article.html) <br />The parameter value has to be encoded with JavaScript’s encodeURIComponent() method or equivalent. <br />Example: si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
| &si<br />
|-<br />
| App Bundle ID<br />
| The app’s unique bundle ID (e.g. com.example.myapp). The ID can be used to look up the App in Apple’s App Store<br />or the Google Play Store.<br />References: https://developer.android.com/studio/build/application-idhttps://developer.apple.com/documentation/appstoreconnectapi/bundle_ids<br />
| &c68=bndlid<br />
|}<br />
{| class="wikitable" style="font-weight:bold;"<br />
|- style="background-color:#32BBB9; color:#002041;"<br />
! Example<br />
|- style="font-weight:normal;"<br />
| si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />c68=bndlid,com.tam.nielsen.com<br />
|}<br />
<br />
== vWrap apiframework Values== <br />
<br />
Nielsen’s vWrap tag uses the existing definition of '''apiframework''' values defined in the IAB’s [https://github.com/InteractiveAdvertisingBureau/AdCOM/blob/master/AdCOM%20v1.0%20FINAL.md#list--api-frameworks- '''AdCOM Specification''' '''1.0''']. This means that existing macros for this parameter in your system should work out of the box with vWrap.<br />
<br />
The vWrap tag supports the numerical values in bold below. In case of '''8''' (SIMID), the DAR Video tag will be inserted as a standard OMID verification client for viewability measurement and it will not interfere with any SIMID components in the ad.<br />
<br />
If a '''0''' or an empty value is given, the resulting VAST will include both OMID and VPAID measurement solutions. This leaves the decision of the measurement method to the video player, which might be advantageous for mixed campaigns that span mobile and web environments.<br />
<br />
{| class="wikitable" style="font-weight:bold;"<br />
|- style="background-color:#F4F5F7;"<br />
! Value<br />
! Definition<br />
|-<br />
| 1<br />
| style="font-weight:normal;" | VPAID 1.0<br />
|-<br />
| 2<br />
| style="font-weight:normal;" | VPAID 2.0<br />
|- style="font-weight:normal; color:#666;"<br />
| 3<br />
| MRAID 1.0<br />
|- style="font-weight:normal; color:#666;"<br />
| 4<br />
| ORMMA<br />
|- style="font-weight:normal; color:#666;"<br />
| 5<br />
| MRAID 2.0<br />
|- style="font-weight:normal; color:#666;"<br />
| 6<br />
| MRAID 3.0<br />
|-<br />
| 7<br />
| style="font-weight:normal;" | OMID 1.0<br />
|-<br />
| 8<br />
| style="font-weight:normal;" | SIMID 1.0<br />
|}<br />
<br />
== SERVER-SIDE TAG DISPATCH ==<br />
The standard way of triggering a Digital Ad Ratings (DAR) tag on mobile in-app or connected devices is for the publisher to trigger the tag upon ad exposure to the user (either directly or via the ad server). This can be described as a client-side initiated tag.<br />
<br />
It is important to note that MRC/IAB measurement standards stipulate that the ad exposure event still be initiated and recorded from the client-side, even if the ad measurement tag (in this case a DAR tag) is physically initiated from the server-side. Evidence may be required (eg. publisher log file or similar) from the MRC/IAB to substantiate that the user was exposed to the ad on their device.<br />
<br />
In addition to the tag parameters covered in the prior sections, the following HTTP headers need to be modified in the DAR calls to support dispatch from a '''server-side''' publisher ad server:<br />
<br />
{| class="wikitable" <br />
|- style="text-align:center; background-color:#c0c0c0; color:#000000;"<br />
! HTTP Headers<br />
! Description of Modifications<br />
|-<br />
| User-Agent (UA)<br />
| This is expected to be the originating client user-agent for the<br /> device where the user was exposed to the ad. The HTTP UA from <br />the client device should be used to populate the HTTP UA in the<br /> server-side connection/ping. DAR leverages the type of<br />device for platform derivation.<br />
|-<br />
| X-Forwarded-For (XFF) IP<br />
| This is expected to be the originating client IP address for the <br />device where the user was exposed to the ad. Note: When the tag<br /> is fired directly from the ad server, the X-Real-IP will be the ad server IP.<br />
|}<br />
<br />
<br />
=== Server Side Tag Notes ===<br />
<br />
* The server-side tag collection only supports mobile in-app and connected device measurement and will not support cookie-based browser measurement.<br />
<br />
* The client’s server-side setup to trigger/send the DAR tag should suppress any Nielsen cookie returned by the Nielsen collection server as a result of the first DAR tag received. If the Nielsen cookie (returned upon receiving the first DAR tag into secure.imrworldwide.com) is not suppressed, then invalid traffic (IVT) filtration will be triggered upon receiving the 2nd and nth tag.<br />
<br />
* The tag received by Nielsen must be TLS v1.2 compliant or greater.<br />
<br />
== About Nielsen ==<br />
<br />
Nielsen shapes the world’s media and content as a global leader in audience measurement, data and analytics. Through our understanding of people and their behaviors across all channels and platforms, we empower our clients with independent and actionable intelligence so they can connect and engage with their audiences—now and into the future.<br />
<br />
An S&amp;P 500 company, Nielsen (NYSE: NLSN) operates around the world in more than 55 countries. Learn more at [http://www.nielsen.com '''www.nielsen.com'''] or [http://www.nielsen.com/investors '''www.nielsen.com/investors'''] and connect with us on social media.<br />
<br />
'''Audience Is Everything®'''</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=Mobile_DAR_Attributes_Requirements&diff=6385Mobile DAR Attributes Requirements2023-06-12T18:13:19Z<p>LaMarHolmes: /* HEM Support (Hashed Email) */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
== Introduction ==<br />
The standard Nielsen Digital Ad Rating (DAR) tag only supports cookie based '''web browser''' viewing on PCs, MACs, and tablets/smartphone (web-browser). However, when ads are served to tablets/smartphones via native '''app-store applications''', the cookie based tag does not function correctly. Additional tag attributes are needed in order for audience reach measurement to function. Example tags are detailed later in this document.<br />
<br />
One way Nielsen clients can accomplish this is by the use of Nielsen’s native iOS/Android App SDK. Nielsen’s App SDK automatically adds these additional tag attributes to the standard cookie based webbrowser tag before the tag is forwarded on to the Nielsen census collection system. However, there is a significant portion of the publisher mobile app universe where it is either not feasible, or desirable to integrate Nielsen’s native App SDK into 3rd party applications.<br />
<br />
The purpose of this document is to detail the tag URL parameters required that are '''additional''' to the standard cookie based web-browser tag.<br />
<br />
The most critical additional parameter required is the insertion of the Advertising ID (IFA / IDFA / AdID) from the users device that has been exposed to the Ad creative.<br />
<br />
If you are reading this document as an Ad server representative then it is assumed that you have published a specification that mobile app publishers follow to pass the appropriate Advertising ID in the Ad request payload. Typically, your Ad server will then expand a macro or label with that value passed in the Ad request URL, insert into the DAR mobile app tag and redirect to Nielsen collections. See s. See [[#Appendix A: Example Implementation]], figure 2 for an example tag workflow.<br />
<br />
The standard way of triggering a Digital Ad Ratings (DAR) tag on Mobile-App is for the publisher app to trigger (either directly or via Ad server) the tag upon Ad exposure to the user. i.e. a client-side initiated tag. If you wish to implement server-side dispatch of mobile in-app DAR tags then see additional section in this document titled '''server-side tag dispatch'''. Please read the rest of this document before reading the section on server-server.<br />
<br />
Once you have completed your integration, you will be required to submit to a short certification. See [[#Appendix B: Implementation, Testing & Certification]]. Certification also grants inclusion to the approved publisher and certified Ad server vendor list.<br />
<br />
'''Important Note:''' for 2018, the MRC has mandated a series of changes to audience measurement that will require additional tag events to be communicated to Nielsen so that we may compute duration weighting etc. You are strongly urged to contact your Nielsen client service representative to seek a briefing from Nielsen on the best technical methods for tagging in order to be compliant with these changes.<br />
<br />
__TOC__<br />
<br />
== Standard DAR Tag ==<br />
The DAR tag is available as a 1x1 pixel. The following pixel/tag parameters must be specified for all DAR tags, 1x1, regardless of implementation type: browser, mobile browser, mobile app or connected device.<br />
<br />
{| class="wikitable" <br />
|-<br />
! Tag Parameter<br />
! Description<br />
|-<br />
| CI<br />
| Client ID: the ID that is associated with the DAR account that processed tag data is associated with. Will always be hardcoded to a Nielsen generated value that comes from the Nielsen campaign management system<br />
|- style="background-color:#eff8ef;"<br />
| AM<br />
| Ad Server: an ad server participating on the campaign media-plan. This is an internal Nielsen generated value when the ad server is indicated on the campaign during setup<br />
|-<br />
| CA<br />
| Campaign Id: this is the ID associated with your DAR campaign. Unless you are creating and managing the Nielsen campaign via the DAR Tag API, then this parameter value will always be generated from the Nielsen campaign management system. Note: often maps to a media-plan I/O Id<br />
|- style="background-color:#eff8ef;"<br />
| CR<br />
| Creative Id: DAR does not currently report at the creative level; can be hard coded ad server id or associated with a macro expansion<br />
|-<br />
| PC<br />
| Placement Id: can be generated by the ad server via macro expansion or generated by the Nielsen campaign management system. Note: often maps to one of Ad Unit Id, Line Item Id or Video Ad Id<br />
|- style="background-color:#eff8ef;"<br />
| CE<br />
| Site Id: the Id that identifies a publisher site that the placement needs to be mapped to. Maps into the Nielsen MarketView database. Note: can be hardcoded to a pre-registered ad server site id in the Nielsen system or a macro expansion where more than one pre-existing site ids have been made known to Nielsen<br />
|-<br />
| R<br />
| Cachebuster (web): timestamp / random number. Generated by ad server<br />
|- style="background-color:#eff8ef;"<br />
| AT<br />
| Fixed value: “view”<br />
|-<br />
| RT<br />
| Fixed value: “banner”<br />
|- style="background-color:#eff8ef;"<br />
| ST<br />
| Fixed value: “image”<br />
|}<br />
<blockquote> Do not URL encode the values</blockquote><br />
<br />
== Additional DAR Tag Parameters for Mobile App Audience Measurement ==<br />
In this section, the additional URL parameters required beyond the standard cookie based web-browser tag are described in detail.<br />
<br />
For each of the tag examples detailed below, we can support both non-secure (http) and secure (https) flavors. The standard cookie based web-browser tag is included below for reference purposes.<br />
<br />
'''Important note:''' the values against each value-pair in the following tags are for illustrative purposes only. Values for CA, PC and CE will vary depending on the specific campaign being measured and capabilities of the Ad server for macro/value expansion. For more detail on the core DAR parameters, please see the '''Nielsen DAR Tag Implementation Guide.'''<br />
<br />
'''Web Browser DAR tag (cookie based persons identification)'''<br />
<code> //secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=<siteid>&r=<timestamp> </code><br />
<br />
'''Mobile-App DAR Tag Extension (IFA based persons identification)'''<br />
<code> //secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=<siteid>&c7=osgrp,IOS&c8=devgrp,PHN&c9=devid,XXXX-XX-XXXXX-XXXX &c10=plt,MBL&c12=apv,<appVersion>&c13=asid,NIELSEN-PROVIDEDID&c14=osver,7.0.4&uoo=0&r=<timestamp> </code><br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold; "<br />
! style="vertical-align:middle;" | Additional DAR Tag<br /> Parameters for Mobile<br />
! style="vertical-align:middle;" | Example<br />
! style="vertical-align:middle;" | Description<br />
! style="vertical-align:middle;" | Mandatory parameter<br />for mDAR?<br />
|-<br />
| style="vertical-align:middle;" | &c7<br />
| &c7=osgrp,IOS<br />
| style="vertical-align:middle;" | OS Grouping<br />
| style="vertical-align:middle;" | <br />
|- style="background-color:#eff8ef;"<br />
| &c8<br />
| &c8=devgrp,PHN<br />
| style="vertical-align:middle;" | Device Grouping<br />
| ✔<br />
|-<br />
| style="vertical-align:middle;" | &c9<br />
| &c9=devid,CB6E9220-EA64-440B-9456-33AD2294C658<br />
| style="vertical-align:middle; " | Advertising ID<br />
| ✔<br />
|- style="background-color:#eff8ef;"<br />
| &c10<br />
| &c10=plt,MBL<br />
| Platform<br />
| ✔<br />
|-<br />
| &c12<br />
| &c12=apv,1<br />
| App Version<br />
| <br />
|- style="background-color:#eff8ef;"<br />
| &c13<br />
| c13=asid,DD8136-4F0B-470B-9ACA-231E818D95BC<br />
| AppID (Nielsen assigned App ID)<br />
| | ✔<br />
|-<br />
| &c14<br />
| &c14=osver,15.1.3<br />
| OS Version<br />
| <br />
|- style="background-color:#eff8ef;"<br />
|&uoo<br />
| &uoo=0<br />
| Opt-out indicator<br />
| ✔ <br />
|-<br />
|&hem_sha256<br />
| <br />
| SHA256 Hashed Email<br />
| <br />
|- style="background-color:#eff8ef;"<br />
| &hem_unknown<br />
| <br />
| Unknown Hashed Algorithm Email<br />
| <br />
|}<br />
<br />
<blockquote>'''Note''': Clients are encouraged to make an effort to always fill-in optional parameters.<br />
<br />
'''Note''': Do not URL encode the values.</blockquote><br />
<br />
== C7 - OS Grouping (Optional) ==<br />
Valid device OS Grouping data values are the following literal values:<br />
* osgrp,IOS<br />
* osgrp,DROID<br />
* osgrp,ANDROID<br />
<blockquote>'''Note''': If one of the above values cannot be specific, then the parameter should not be included in the call.</blockquote><br />
<br />
== C8 - Device Grouping (Mandatory)==<br />
Valid literal values for phone, tablet, portable media player (iPod) and unknown are as follows:<br />
* devgrp,PHN - Phone<br />
* devgrp,TAB - Tablet<br />
* devgrp,PMP - Portable Media Player (iPod)<br />
* devgrp,UNWN - Unknown/Unclassified<br />
* devgrp,DSK - Desktop<br />
* devgrp,STV ← CTV/OTT Device<br />
==== Notes ====<br />
* Mandatory for accurate measurement, and if unable to pass, Nielsen cannot guarantee the impression will be classified correctly. <br />
* “UNWN” will result in Nielsen attempting an introspection of the User Agent in the HTTP request sent against Device Atlas for classification. <br />
* “STV” is the default value for OTT when the specific device value isn’t passed.</blockquote><br />
<br />
== C9 - Advertising ID (Mandatory) ==<br />
This is the advertiser ID for the client’s mobile device. IDFA for iOS, Google Advertising ID for Android:<br />
* devid,<IDFA><br />
* devid,<IFA><br />
* devid,<Google Advertising ID><br />
<br><br />
{| class="wikitable" <br />
|- style="background-color:#efefef;"<br />
! colspan="2" | Below are the supported hash methods for the devid value:<br />
|- style="vertical-align:bottom;"<br />
| Clear Text<br />
| c9=devid,CB6E9220-EA64-440B-9456-33AD2294C658<br />
|- style="vertical-align:bottom;"<br />
| sha256<br />
| c9=devid,136844f58ab7f7e991ea4b5150ec767c9327e1391c839a3b3612d418ae875391<br />
|- style="vertical-align:bottom;"<br />
| Sha1<br />
| c9=devid,a08039967f4817ada4a7f331369eea522ad415a7<br />
|- style="vertical-align:bottom;"<br />
| md5<br />
| c9=devid,53d8c474c1e871bdd34f14785dbcfd94<br />
|}<br />
<br />
==== Notes ====<br />
For Android devices, the Google Advertiser ID should be used as the default and the Android ID as the second option.<br><br />
<br />
* If C9 is <empty>, upon receiving the ping, the Nielsen collection server will attempt a 302 redirect to the data provider per the regular DAR pixel for browsers.</blockquote><br />
* As of August 1, 2014, Google is enforcing use of the Advertising ID for advertising and user analytics (http://play.google.com/about/developer-content-policy.html).<br />
<blockquote>'' "Beginning August 1st 2014, all updates and new apps uploaded to the Play Store must use the advertising ID (when available on a device) in lieu of any other device identifiers for any advertising purposes."</blockquote><br />
* It is preferred that the IDFA or Google Advertising ID be sent as is from the mobile device (“cleartext”). However, if mandated, we will support SHA256 hashed values with no-salt. Passing a hashed value (and/or salting) using any other standard will result in a failed match by the data provider upon receiving the ping. In turn, this results in impressions surfacing in the DAR unmeasurable audience totals. Please contact Nielsen if you anticipate a large percentage of hashed values coming in from your publisher clients.<br />
<br />
=== Privacy, Ad Tracking, and Ad Targeting ===<br />
In newer iterations of the iOS and Android device operating systems, a facility exists allowing users to “opt-out” of “Ad Tracking”. It is Nielsen’s interpretation that this setting is primarily designed to allow users to specify opt-out of Ad Targeting rather than Ad Measurement. DAR<br />
does not provide Ad Targeting data.<br />
<br />
However, it is also Nielsen’s position that the publisher or Ad network should provide a mechanism to also allow a user to opt-out of Ad Measurement. The Nielsen SDK will honor the Nielsen Ad Measurement opt-out settings configurable @ http://www.nielsen.com/us/en/campaigns/privacy-policy-opt-out.html.<br />
<br />
However if the integration approach described in this document is being used instead of the Nielsen SDK then '''YOU''' as the publisher or Ad network must provide a capability to opt-out of Ad Measurement as the configuration on www.nielsen.com will not be detectable. You may<br />
elect to interpret the iOS / Android “Ad Tracking” setting for the purpose of limit Ad measurement or provide a separate discreet mechanism to allow a user to opt-out of Ad measurement.<br />
<br />
Please see '''&uoo''' later in this document for implementation details of the optout indicator.<br />
<br />
For additional clarification on privacy policy, please contact your Nielsen representative.<br />
<br />
== C10 - Platform (Mandatory) ==<br />
To determine this value, Nielsen suggests that the ad network leverage user agent information to determine if the client device is either a mobile or desktop device.<br />
<br />
Valid literal values for mobile and desktop data values are as follows:<br />
* plt,MBL<br />
* plt,DSK<br />
* plt,OTT<br />
==== Notes ====<br />
* Mandatory for accurate measurement, and if unable to pass, Nielsen cannot guarantee the impression will be classified correctly. <br />
* Omitting c10, or a value in c10, will result in Nielsen attempting an introspection of the User Agent in the HTTP request sent against Device Atlas for classification. <br />
* “OTT” (Connective Devices) is a valid value that is populated by participating vendors (Amazon, Hulu and Roku). Non-participating vendors will be unmeasurable volumetric metric only.<br />
<br />
== C12 - App Version (Optional) ==<br />
This is the version of the ad network system software or SDK that is implemented in this extension. Although this field is not required, this feature can be useful for troubleshooting purposes following deployment.<br />
* apv,<N.N><br />
<br />
== C13 - AppID ==<br />
This Nielsen provided ID is unique to the ad network and is required for certification.<br />
* asid,<NNNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN><br />
An App ID will be provided for testing. A separate App ID will be provided for production use. Please request from your Nielsen representative.<br />
<blockquote>'''Note''': If you are a publisher leveraging the non-SDK solution, you will be provided with a unique App ID for each combination of app and device OS type.</blockquote><br />
<br />
== C14 - OS Version (Optional) ==<br />
Operating system version<br />
* osver,<OS Version><br />
Example: for iOS -> 7.0.4<br />
<br />
== UOO - Opt Out ==<br />
Opt-out parameter<br />
* <Boolean state><br />
<Boolean state> is a Boolean representation of whether the user is opting out or not.<br />
<br />
The absence of uoo in the tag is interpreted as an implicit opt-in. i.e. not opting out.<br />
<br />
The following pairings of opt-out are supported. '''Important:''' you must choose one set of paired values only and inform your Nielsen representative.<br />
{| class="wikitable"<br />
|-<br />
! Opt-out !! Opt-in<br />
|-<br />
| uoo=true || uoo=false<br />
|-<br />
| uoo=1 || uoo=0<br />
|-<br />
| uoo=yes || uoo=no<br />
|}<br />
<blockquote>'''Note''': if your Ad server is not capable os supporting the discrete &uoo parameter then you can set the c9 value to <code>devid,optout</code> (for example <code>…&c8=PHN&c9=devid,optout&c10=MBL…</code>)</blockquote><br />
== Additional Parameters == <br />
This section describes several important additional parameters that the DAR tag can support, specifically Hashed Email, and UID2 values. Please note that all parameters are case-sensitive.<br />
<br />
Please work with your Nielsen Technical Account Manager to decide which of the following parameters to append to the standard DAR tag.<br />
=== HEM Support (Hashed Email) ===<br />
Please use the parameter that matches your hashing algorithm. For example, if you are using sha256 to encode the email address, then use hem_sha256={encrypted_value_here}<br />
{| class="wikitable" style="font-weight:bold; background-color:#EAECF0;"<br />
|-<br />
! Name<br />
! Description<br />
! Available Tag Parameters<br />
|- style="font-weight:normal; background-color:#F8F9FA;"<br />
| Hashed Email<br />
| User’s email address that has been run through the sha256 hashing algorithm to create a unique hexadecimal string.<br /> If a client is unable to determine hashing type, they should pass<br />using &hem_unknown parameter.<br />
| &hem_unknown<br />&hem_sha256<br /><br />
|}<br />
{| class="wikitable" style="font-weight:bold;"<br />
|- style="background-color:#dae8fc; color:#002041;"<br />
! Example<br />
|- style="font-weight:normal;"<br />
| hem_sha256=tMmiiTI7IaAcPpQPFQ65uMVCWH8av9jw4cwf/F5HVRQ=<br />
|}<br />
<br />
=== Unified ID ===<br />
{| class="wikitable" style="background-color:#F8F9FA;"<br />
|- style="font-weight:bold; background-color:#EAECF0;"<br />
! Name<br />
! Description<br />
! Available Tag Parameters<br />
|-<br />
| Unified ID 2.0<br />
| An identifier based on a user’s verifiable PII (e.g. hashed email). UID2.0 was initially created by The Trade Desk (TTD)<br />and is now managed by Prebid.<br />
| &uid2<br />
|-<br />
| Unified ID 2.0 Token<br />
| Encrypted Unified ID 2.0<br />
| &uid_token<br />
|}<br />
{| class="wikitable" style="font-weight:bold;"<br />
|- style="background-color:#32BBB9; color:#002041;"<br />
! Example<br />
|- style="font-weight:normal;"<br />
| uid2=MTKVpUAzwYAPnHrtfE0wlINOMzhU7UUEjjVdCdRu63k=<br />uid_token=AgAAAAPFR0zA5ogv/yaAPiUsAdZPsfqS8QlDSGxAB+rr8yekFs3AjLYVk5qqqiyV2XHbSuwzHmxSlLeQeKQI1mp015jsNnpX5<br />/xGgXldcgVz+gFnyh3T8/3agMwRmyrhCxG4oH2C7fc48AQk2eotE7FW0ZDEYM8fD9ZxDaxFUC/OV3OuZA&<br />
|}<br />
<br />
== Server-Side Tag Dispatch ==<br />
The standard way of triggering a Digital Ad Ratings (DAR) tag on Mobile-App is for the publisher app to trigger (either directly or via Ad server) the tag upon Ad exposure to the user. i.e. a client-side initiated tag.<br />
<br />
It is important to note that MRC/IAB measurement standards stipulate that the Ad exposure event still be initiated and recorded from the client-side, even if the Ad measurement tag (in this case a DAR tag) is physically initiated from the server-side. Evidence may be required (publisher log file or similar) from the MRC/IAB that the user was exposed to the Ad creative on their device.<br />
<br />
The following additional changes to the standard mobile-app DAR tag are required to support dispatch the DAR tag from a '''server-side''' publisher ad server:<br />
<br />
#'''X-Forwarded-For (XFF) IP:''' The original client IP address must be passed in the X-Forwarded-For (XFF) HTTP header field. When the impression is fired directly from the Ad Server, the XReal-IP will be the Ad Server IP.<br />
#'''Cachebuster:''' Already present in the DAR tag, this now becomes mandatory. A cachebuster or random number ensures a new call is made to the Ad Server. By including a cachebuster ('r' parameter), the tag will not be cached. The timestamp of when the Ad was served can be used.<br />
#'''User Agent (UA):''' The HTTP UA from the client device should be used to populate the HTTP UA in the server-server connection/ping.<br />
#'''TLS:''' the tag received by Nielsen must be TLS v1.2 compliant or greater.<br />
<br />
==== Important notes ====<br />
* the current iteration of server-server tag collection only supports mobile-app (IFA and AAID) and will NOT support cookie based audience measurement.<br />
* The client’s server-server setup that is going to trigger/send the DAR tag should suppress any Nielsen cookie returned by the Nielsen collection server as a result of the first DAR tag received. If the Nielsen cookie (returned upon receiving the first DAR tag into secure.imrworldwide.com) is not suppressed then invalid traffic (IVT) filtration will quickly be triggered upon receiving the 2nd and nth tag.<br />
<br />
== Appendix A: Example Implementation ==<br />
In the below examples, you will see the overall DAR flow (Figure 1) and a detailed illustrative Ad Request / Response model (Figure 2).<br />
<br />
<br />
<div align="center">'''Figure 1 – End to End Data Flow'''</div><br />
<br />
[[File:mDAR_Dataflow.png|center|link=]]<br />
<br />
Nielsen certified publishers and platforms will append the new parameters (below) with the appropriate URL safe values passed to Nielsen’s current DAR tag. The current DAR tag should be acquired using the existing processes for each campaign/placement. <br />
<br />
<blockquote><code>'''&c7'''=osgrp,IOS'''&c8'''=devgrp,PHN'''&c9'''=devid,XXXX-XX-XXXXXXXXX'''&c10'''=plt,MBL'''&c12'''=apv,AppVersion'''&c13'''=asid,XXXX-XX-XXXX-XXXX</code></blockquote><br />
<br />
<br />
<div align="center">'''Figure 2 – Illustrative Ad Request / Ad Response'''</div><br />
<br />
[[File:ad_response.png|center|link=]]<br />
<br />
The above is an example of how an Ad server is supporting the build of mobile DAR tags for its publisher clients.<br />
*Step 2 in Figure 1 is a summary of steps 1 and 2 in Figure 2 above.<br />
*Steps 3 and 4 in Figure 1 is a summary of steps 3 through 9 in Figure 2 above.<br />
<br />
== Appendix B: Implementation, Testing & Certification ==<br />
Once you have integrated the ping per the above specs, Nielsen requires you to pass through a one-time certification before traffic can be accepted into the production environment.<br />
<br />
The overall process is:<br />
* Valid DAR contract or NDA is in place.<br />
* Kick-off meeting with Nielsen onboarding team.<br />
* Confirm meet minimums testing requirements:<br />
** Host Ad/Tag for in-app delivery<br />
** Can pass opt-out back to Nielsen<br />
** Can pass Device ID in cleartext or SHA-256<br />
* Nielsen provides the mDAR testing form that includes the test App ID and the test tag<br />
* Identify the live campaigns for initial testing and run the test tag; suggest 5,000-10,000 impressions.<br />
* Nielsen validates the data received from the test and confirms the initial test successful and provides the production App ID.<br />
* Ensure contracts are in place for external test campaign with Nielsen Client Service team.<br />
* Identify another live campaigns for production testing with production tag and app ID.<br />
* Nielsen validates the data received from the final test and confirms certification for any DAR countries tested.<br />
==== Goals ====<br />
* To test in full DAR E2E environment, receive matches from data provider for demographics and correct identification of mobile impressions.<br />
* To test that all minimum requirements in step 3 are passed to Nielsen with no issues.<br />
* To test in a full DAR end-to-end environment, receive matches from data providers for demographics and correct identification of mobile impressions.</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=Mobile_DAR_Attributes_Requirements&diff=6384Mobile DAR Attributes Requirements2023-06-12T18:12:26Z<p>LaMarHolmes: /* Additional DAR Tag Parameters for Mobile App Audience Measurement */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
== Introduction ==<br />
The standard Nielsen Digital Ad Rating (DAR) tag only supports cookie based '''web browser''' viewing on PCs, MACs, and tablets/smartphone (web-browser). However, when ads are served to tablets/smartphones via native '''app-store applications''', the cookie based tag does not function correctly. Additional tag attributes are needed in order for audience reach measurement to function. Example tags are detailed later in this document.<br />
<br />
One way Nielsen clients can accomplish this is by the use of Nielsen’s native iOS/Android App SDK. Nielsen’s App SDK automatically adds these additional tag attributes to the standard cookie based webbrowser tag before the tag is forwarded on to the Nielsen census collection system. However, there is a significant portion of the publisher mobile app universe where it is either not feasible, or desirable to integrate Nielsen’s native App SDK into 3rd party applications.<br />
<br />
The purpose of this document is to detail the tag URL parameters required that are '''additional''' to the standard cookie based web-browser tag.<br />
<br />
The most critical additional parameter required is the insertion of the Advertising ID (IFA / IDFA / AdID) from the users device that has been exposed to the Ad creative.<br />
<br />
If you are reading this document as an Ad server representative then it is assumed that you have published a specification that mobile app publishers follow to pass the appropriate Advertising ID in the Ad request payload. Typically, your Ad server will then expand a macro or label with that value passed in the Ad request URL, insert into the DAR mobile app tag and redirect to Nielsen collections. See s. See [[#Appendix A: Example Implementation]], figure 2 for an example tag workflow.<br />
<br />
The standard way of triggering a Digital Ad Ratings (DAR) tag on Mobile-App is for the publisher app to trigger (either directly or via Ad server) the tag upon Ad exposure to the user. i.e. a client-side initiated tag. If you wish to implement server-side dispatch of mobile in-app DAR tags then see additional section in this document titled '''server-side tag dispatch'''. Please read the rest of this document before reading the section on server-server.<br />
<br />
Once you have completed your integration, you will be required to submit to a short certification. See [[#Appendix B: Implementation, Testing & Certification]]. Certification also grants inclusion to the approved publisher and certified Ad server vendor list.<br />
<br />
'''Important Note:''' for 2018, the MRC has mandated a series of changes to audience measurement that will require additional tag events to be communicated to Nielsen so that we may compute duration weighting etc. You are strongly urged to contact your Nielsen client service representative to seek a briefing from Nielsen on the best technical methods for tagging in order to be compliant with these changes.<br />
<br />
__TOC__<br />
<br />
== Standard DAR Tag ==<br />
The DAR tag is available as a 1x1 pixel. The following pixel/tag parameters must be specified for all DAR tags, 1x1, regardless of implementation type: browser, mobile browser, mobile app or connected device.<br />
<br />
{| class="wikitable" <br />
|-<br />
! Tag Parameter<br />
! Description<br />
|-<br />
| CI<br />
| Client ID: the ID that is associated with the DAR account that processed tag data is associated with. Will always be hardcoded to a Nielsen generated value that comes from the Nielsen campaign management system<br />
|- style="background-color:#eff8ef;"<br />
| AM<br />
| Ad Server: an ad server participating on the campaign media-plan. This is an internal Nielsen generated value when the ad server is indicated on the campaign during setup<br />
|-<br />
| CA<br />
| Campaign Id: this is the ID associated with your DAR campaign. Unless you are creating and managing the Nielsen campaign via the DAR Tag API, then this parameter value will always be generated from the Nielsen campaign management system. Note: often maps to a media-plan I/O Id<br />
|- style="background-color:#eff8ef;"<br />
| CR<br />
| Creative Id: DAR does not currently report at the creative level; can be hard coded ad server id or associated with a macro expansion<br />
|-<br />
| PC<br />
| Placement Id: can be generated by the ad server via macro expansion or generated by the Nielsen campaign management system. Note: often maps to one of Ad Unit Id, Line Item Id or Video Ad Id<br />
|- style="background-color:#eff8ef;"<br />
| CE<br />
| Site Id: the Id that identifies a publisher site that the placement needs to be mapped to. Maps into the Nielsen MarketView database. Note: can be hardcoded to a pre-registered ad server site id in the Nielsen system or a macro expansion where more than one pre-existing site ids have been made known to Nielsen<br />
|-<br />
| R<br />
| Cachebuster (web): timestamp / random number. Generated by ad server<br />
|- style="background-color:#eff8ef;"<br />
| AT<br />
| Fixed value: “view”<br />
|-<br />
| RT<br />
| Fixed value: “banner”<br />
|- style="background-color:#eff8ef;"<br />
| ST<br />
| Fixed value: “image”<br />
|}<br />
<blockquote> Do not URL encode the values</blockquote><br />
<br />
== Additional DAR Tag Parameters for Mobile App Audience Measurement ==<br />
In this section, the additional URL parameters required beyond the standard cookie based web-browser tag are described in detail.<br />
<br />
For each of the tag examples detailed below, we can support both non-secure (http) and secure (https) flavors. The standard cookie based web-browser tag is included below for reference purposes.<br />
<br />
'''Important note:''' the values against each value-pair in the following tags are for illustrative purposes only. Values for CA, PC and CE will vary depending on the specific campaign being measured and capabilities of the Ad server for macro/value expansion. For more detail on the core DAR parameters, please see the '''Nielsen DAR Tag Implementation Guide.'''<br />
<br />
'''Web Browser DAR tag (cookie based persons identification)'''<br />
<code> //secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=<siteid>&r=<timestamp> </code><br />
<br />
'''Mobile-App DAR Tag Extension (IFA based persons identification)'''<br />
<code> //secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=<siteid>&c7=osgrp,IOS&c8=devgrp,PHN&c9=devid,XXXX-XX-XXXXX-XXXX &c10=plt,MBL&c12=apv,<appVersion>&c13=asid,NIELSEN-PROVIDEDID&c14=osver,7.0.4&uoo=0&r=<timestamp> </code><br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold; "<br />
! style="vertical-align:middle;" | Additional DAR Tag<br /> Parameters for Mobile<br />
! style="vertical-align:middle;" | Example<br />
! style="vertical-align:middle;" | Description<br />
! style="vertical-align:middle;" | Mandatory parameter<br />for mDAR?<br />
|-<br />
| style="vertical-align:middle;" | &c7<br />
| &c7=osgrp,IOS<br />
| style="vertical-align:middle;" | OS Grouping<br />
| style="vertical-align:middle;" | <br />
|- style="background-color:#eff8ef;"<br />
| &c8<br />
| &c8=devgrp,PHN<br />
| style="vertical-align:middle;" | Device Grouping<br />
| ✔<br />
|-<br />
| style="vertical-align:middle;" | &c9<br />
| &c9=devid,CB6E9220-EA64-440B-9456-33AD2294C658<br />
| style="vertical-align:middle; " | Advertising ID<br />
| ✔<br />
|- style="background-color:#eff8ef;"<br />
| &c10<br />
| &c10=plt,MBL<br />
| Platform<br />
| ✔<br />
|-<br />
| &c12<br />
| &c12=apv,1<br />
| App Version<br />
| <br />
|- style="background-color:#eff8ef;"<br />
| &c13<br />
| c13=asid,DD8136-4F0B-470B-9ACA-231E818D95BC<br />
| AppID (Nielsen assigned App ID)<br />
| | ✔<br />
|-<br />
| &c14<br />
| &c14=osver,15.1.3<br />
| OS Version<br />
| <br />
|- style="background-color:#eff8ef;"<br />
|&uoo<br />
| &uoo=0<br />
| Opt-out indicator<br />
| ✔ <br />
|-<br />
|&hem_sha256<br />
| <br />
| SHA256 Hashed Email<br />
| <br />
|- style="background-color:#eff8ef;"<br />
| &hem_unknown<br />
| <br />
| Unknown Hashed Algorithm Email<br />
| <br />
|}<br />
<br />
<blockquote>'''Note''': Clients are encouraged to make an effort to always fill-in optional parameters.<br />
<br />
'''Note''': Do not URL encode the values.</blockquote><br />
<br />
== C7 - OS Grouping (Optional) ==<br />
Valid device OS Grouping data values are the following literal values:<br />
* osgrp,IOS<br />
* osgrp,DROID<br />
* osgrp,ANDROID<br />
<blockquote>'''Note''': If one of the above values cannot be specific, then the parameter should not be included in the call.</blockquote><br />
<br />
== C8 - Device Grouping (Mandatory)==<br />
Valid literal values for phone, tablet, portable media player (iPod) and unknown are as follows:<br />
* devgrp,PHN - Phone<br />
* devgrp,TAB - Tablet<br />
* devgrp,PMP - Portable Media Player (iPod)<br />
* devgrp,UNWN - Unknown/Unclassified<br />
* devgrp,DSK - Desktop<br />
* devgrp,STV ← CTV/OTT Device<br />
==== Notes ====<br />
* Mandatory for accurate measurement, and if unable to pass, Nielsen cannot guarantee the impression will be classified correctly. <br />
* “UNWN” will result in Nielsen attempting an introspection of the User Agent in the HTTP request sent against Device Atlas for classification. <br />
* “STV” is the default value for OTT when the specific device value isn’t passed.</blockquote><br />
<br />
== C9 - Advertising ID (Mandatory) ==<br />
This is the advertiser ID for the client’s mobile device. IDFA for iOS, Google Advertising ID for Android:<br />
* devid,<IDFA><br />
* devid,<IFA><br />
* devid,<Google Advertising ID><br />
<br><br />
{| class="wikitable" <br />
|- style="background-color:#efefef;"<br />
! colspan="2" | Below are the supported hash methods for the devid value:<br />
|- style="vertical-align:bottom;"<br />
| Clear Text<br />
| c9=devid,CB6E9220-EA64-440B-9456-33AD2294C658<br />
|- style="vertical-align:bottom;"<br />
| sha256<br />
| c9=devid,136844f58ab7f7e991ea4b5150ec767c9327e1391c839a3b3612d418ae875391<br />
|- style="vertical-align:bottom;"<br />
| Sha1<br />
| c9=devid,a08039967f4817ada4a7f331369eea522ad415a7<br />
|- style="vertical-align:bottom;"<br />
| md5<br />
| c9=devid,53d8c474c1e871bdd34f14785dbcfd94<br />
|}<br />
<br />
==== Notes ====<br />
For Android devices, the Google Advertiser ID should be used as the default and the Android ID as the second option.<br><br />
<br />
* If C9 is <empty>, upon receiving the ping, the Nielsen collection server will attempt a 302 redirect to the data provider per the regular DAR pixel for browsers.</blockquote><br />
* As of August 1, 2014, Google is enforcing use of the Advertising ID for advertising and user analytics (http://play.google.com/about/developer-content-policy.html).<br />
<blockquote>'' "Beginning August 1st 2014, all updates and new apps uploaded to the Play Store must use the advertising ID (when available on a device) in lieu of any other device identifiers for any advertising purposes."</blockquote><br />
* It is preferred that the IDFA or Google Advertising ID be sent as is from the mobile device (“cleartext”). However, if mandated, we will support SHA256 hashed values with no-salt. Passing a hashed value (and/or salting) using any other standard will result in a failed match by the data provider upon receiving the ping. In turn, this results in impressions surfacing in the DAR unmeasurable audience totals. Please contact Nielsen if you anticipate a large percentage of hashed values coming in from your publisher clients.<br />
<br />
=== Privacy, Ad Tracking, and Ad Targeting ===<br />
In newer iterations of the iOS and Android device operating systems, a facility exists allowing users to “opt-out” of “Ad Tracking”. It is Nielsen’s interpretation that this setting is primarily designed to allow users to specify opt-out of Ad Targeting rather than Ad Measurement. DAR<br />
does not provide Ad Targeting data.<br />
<br />
However, it is also Nielsen’s position that the publisher or Ad network should provide a mechanism to also allow a user to opt-out of Ad Measurement. The Nielsen SDK will honor the Nielsen Ad Measurement opt-out settings configurable @ http://www.nielsen.com/us/en/campaigns/privacy-policy-opt-out.html.<br />
<br />
However if the integration approach described in this document is being used instead of the Nielsen SDK then '''YOU''' as the publisher or Ad network must provide a capability to opt-out of Ad Measurement as the configuration on www.nielsen.com will not be detectable. You may<br />
elect to interpret the iOS / Android “Ad Tracking” setting for the purpose of limit Ad measurement or provide a separate discreet mechanism to allow a user to opt-out of Ad measurement.<br />
<br />
Please see '''&uoo''' later in this document for implementation details of the optout indicator.<br />
<br />
For additional clarification on privacy policy, please contact your Nielsen representative.<br />
<br />
== C10 - Platform (Mandatory) ==<br />
To determine this value, Nielsen suggests that the ad network leverage user agent information to determine if the client device is either a mobile or desktop device.<br />
<br />
Valid literal values for mobile and desktop data values are as follows:<br />
* plt,MBL<br />
* plt,DSK<br />
* plt,OTT<br />
==== Notes ====<br />
* Mandatory for accurate measurement, and if unable to pass, Nielsen cannot guarantee the impression will be classified correctly. <br />
* Omitting c10, or a value in c10, will result in Nielsen attempting an introspection of the User Agent in the HTTP request sent against Device Atlas for classification. <br />
* “OTT” (Connective Devices) is a valid value that is populated by participating vendors (Amazon, Hulu and Roku). Non-participating vendors will be unmeasurable volumetric metric only.<br />
<br />
== C12 - App Version (Optional) ==<br />
This is the version of the ad network system software or SDK that is implemented in this extension. Although this field is not required, this feature can be useful for troubleshooting purposes following deployment.<br />
* apv,<N.N><br />
<br />
== C13 - AppID ==<br />
This Nielsen provided ID is unique to the ad network and is required for certification.<br />
* asid,<NNNNNNNNN-NNNN-NNNN-NNNN-NNNNNNNNNNNN><br />
An App ID will be provided for testing. A separate App ID will be provided for production use. Please request from your Nielsen representative.<br />
<blockquote>'''Note''': If you are a publisher leveraging the non-SDK solution, you will be provided with a unique App ID for each combination of app and device OS type.</blockquote><br />
<br />
== C14 - OS Version (Optional) ==<br />
Operating system version<br />
* osver,<OS Version><br />
Example: for iOS -> 7.0.4<br />
<br />
== UOO - Opt Out ==<br />
Opt-out parameter<br />
* <Boolean state><br />
<Boolean state> is a Boolean representation of whether the user is opting out or not.<br />
<br />
The absence of uoo in the tag is interpreted as an implicit opt-in. i.e. not opting out.<br />
<br />
The following pairings of opt-out are supported. '''Important:''' you must choose one set of paired values only and inform your Nielsen representative.<br />
{| class="wikitable"<br />
|-<br />
! Opt-out !! Opt-in<br />
|-<br />
| uoo=true || uoo=false<br />
|-<br />
| uoo=1 || uoo=0<br />
|-<br />
| uoo=yes || uoo=no<br />
|}<br />
<blockquote>'''Note''': if your Ad server is not capable os supporting the discrete &uoo parameter then you can set the c9 value to <code>devid,optout</code> (for example <code>…&c8=PHN&c9=devid,optout&c10=MBL…</code>)</blockquote><br />
== Additional Parameters == <br />
This section describes several important additional parameters that the DAR tag can support, specifically Hashed Email, and UID2 values. Please note that all parameters are case-sensitive.<br />
<br />
Please work with your Nielsen Technical Account Manager to decide which of the following parameters to append to the standard DAR tag.<br />
=== HEM Support (Hashed Email) ===<br />
Please use the parameter that matches your hashing algorithm. For example, if you are using sha256 to encode the email address, then use hem_sha256={encrypted_value_here}<br />
{| class="wikitable" style="font-weight:bold; background-color:#EAECF0;"<br />
|-<br />
! Name<br />
! Description<br />
! Available Tag Parameters<br />
|- style="font-weight:normal; background-color:#F8F9FA;"<br />
| Hashed Email<br />
| User’s email address that has been run through a hashing algorithm<br />(e.g. SHA256, MD5, SHA1) to create a unique hexadecimal string.<br /> If a client is unable to determine hashing type, they should pass<br />using &hem_unknown parameter.<br />
| &hem_unknown<br />&hem_sha256<br />&hem_md5<br />&hem_sha1<br />
|}<br />
{| class="wikitable" style="font-weight:bold;"<br />
|- style="background-color:#dae8fc; color:#002041;"<br />
! Example<br />
|- style="font-weight:normal;"<br />
| hem_sha256=tMmiiTI7IaAcPpQPFQ65uMVCWH8av9jw4cwf/F5HVRQ=<br />
|}<br />
<br />
=== Unified ID ===<br />
{| class="wikitable" style="background-color:#F8F9FA;"<br />
|- style="font-weight:bold; background-color:#EAECF0;"<br />
! Name<br />
! Description<br />
! Available Tag Parameters<br />
|-<br />
| Unified ID 2.0<br />
| An identifier based on a user’s verifiable PII (e.g. hashed email). UID2.0 was initially created by The Trade Desk (TTD)<br />and is now managed by Prebid.<br />
| &uid2<br />
|-<br />
| Unified ID 2.0 Token<br />
| Encrypted Unified ID 2.0<br />
| &uid_token<br />
|}<br />
{| class="wikitable" style="font-weight:bold;"<br />
|- style="background-color:#32BBB9; color:#002041;"<br />
! Example<br />
|- style="font-weight:normal;"<br />
| uid2=MTKVpUAzwYAPnHrtfE0wlINOMzhU7UUEjjVdCdRu63k=<br />uid_token=AgAAAAPFR0zA5ogv/yaAPiUsAdZPsfqS8QlDSGxAB+rr8yekFs3AjLYVk5qqqiyV2XHbSuwzHmxSlLeQeKQI1mp015jsNnpX5<br />/xGgXldcgVz+gFnyh3T8/3agMwRmyrhCxG4oH2C7fc48AQk2eotE7FW0ZDEYM8fD9ZxDaxFUC/OV3OuZA&<br />
|}<br />
<br />
== Server-Side Tag Dispatch ==<br />
The standard way of triggering a Digital Ad Ratings (DAR) tag on Mobile-App is for the publisher app to trigger (either directly or via Ad server) the tag upon Ad exposure to the user. i.e. a client-side initiated tag.<br />
<br />
It is important to note that MRC/IAB measurement standards stipulate that the Ad exposure event still be initiated and recorded from the client-side, even if the Ad measurement tag (in this case a DAR tag) is physically initiated from the server-side. Evidence may be required (publisher log file or similar) from the MRC/IAB that the user was exposed to the Ad creative on their device.<br />
<br />
The following additional changes to the standard mobile-app DAR tag are required to support dispatch the DAR tag from a '''server-side''' publisher ad server:<br />
<br />
#'''X-Forwarded-For (XFF) IP:''' The original client IP address must be passed in the X-Forwarded-For (XFF) HTTP header field. When the impression is fired directly from the Ad Server, the XReal-IP will be the Ad Server IP.<br />
#'''Cachebuster:''' Already present in the DAR tag, this now becomes mandatory. A cachebuster or random number ensures a new call is made to the Ad Server. By including a cachebuster ('r' parameter), the tag will not be cached. The timestamp of when the Ad was served can be used.<br />
#'''User Agent (UA):''' The HTTP UA from the client device should be used to populate the HTTP UA in the server-server connection/ping.<br />
#'''TLS:''' the tag received by Nielsen must be TLS v1.2 compliant or greater.<br />
<br />
==== Important notes ====<br />
* the current iteration of server-server tag collection only supports mobile-app (IFA and AAID) and will NOT support cookie based audience measurement.<br />
* The client’s server-server setup that is going to trigger/send the DAR tag should suppress any Nielsen cookie returned by the Nielsen collection server as a result of the first DAR tag received. If the Nielsen cookie (returned upon receiving the first DAR tag into secure.imrworldwide.com) is not suppressed then invalid traffic (IVT) filtration will quickly be triggered upon receiving the 2nd and nth tag.<br />
<br />
== Appendix A: Example Implementation ==<br />
In the below examples, you will see the overall DAR flow (Figure 1) and a detailed illustrative Ad Request / Response model (Figure 2).<br />
<br />
<br />
<div align="center">'''Figure 1 – End to End Data Flow'''</div><br />
<br />
[[File:mDAR_Dataflow.png|center|link=]]<br />
<br />
Nielsen certified publishers and platforms will append the new parameters (below) with the appropriate URL safe values passed to Nielsen’s current DAR tag. The current DAR tag should be acquired using the existing processes for each campaign/placement. <br />
<br />
<blockquote><code>'''&c7'''=osgrp,IOS'''&c8'''=devgrp,PHN'''&c9'''=devid,XXXX-XX-XXXXXXXXX'''&c10'''=plt,MBL'''&c12'''=apv,AppVersion'''&c13'''=asid,XXXX-XX-XXXX-XXXX</code></blockquote><br />
<br />
<br />
<div align="center">'''Figure 2 – Illustrative Ad Request / Ad Response'''</div><br />
<br />
[[File:ad_response.png|center|link=]]<br />
<br />
The above is an example of how an Ad server is supporting the build of mobile DAR tags for its publisher clients.<br />
*Step 2 in Figure 1 is a summary of steps 1 and 2 in Figure 2 above.<br />
*Steps 3 and 4 in Figure 1 is a summary of steps 3 through 9 in Figure 2 above.<br />
<br />
== Appendix B: Implementation, Testing & Certification ==<br />
Once you have integrated the ping per the above specs, Nielsen requires you to pass through a one-time certification before traffic can be accepted into the production environment.<br />
<br />
The overall process is:<br />
* Valid DAR contract or NDA is in place.<br />
* Kick-off meeting with Nielsen onboarding team.<br />
* Confirm meet minimums testing requirements:<br />
** Host Ad/Tag for in-app delivery<br />
** Can pass opt-out back to Nielsen<br />
** Can pass Device ID in cleartext or SHA-256<br />
* Nielsen provides the mDAR testing form that includes the test App ID and the test tag<br />
* Identify the live campaigns for initial testing and run the test tag; suggest 5,000-10,000 impressions.<br />
* Nielsen validates the data received from the test and confirms the initial test successful and provides the production App ID.<br />
* Ensure contracts are in place for external test campaign with Nielsen Client Service team.<br />
* Identify another live campaigns for production testing with production tag and app ID.<br />
* Nielsen validates the data received from the final test and confirms certification for any DAR countries tested.<br />
==== Goals ====<br />
* To test in full DAR E2E environment, receive matches from data provider for demographics and correct identification of mobile impressions.<br />
* To test that all minimum requirements in step 3 are passed to Nielsen with no issues.<br />
* To test in a full DAR end-to-end environment, receive matches from data providers for demographics and correct identification of mobile impressions.</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=AGF_Metadata_Convention&diff=6042AGF Metadata Convention2022-11-14T19:23:45Z<p>LaMarHolmes: /* Video Measurement */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|AGF Implementation Documentation}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
__TOC__<br />
<br />
= AGF Metadata Convention =<br />
<br />
The Metadata can pass through key values using the Nielsen reserved keys. The keys and values are listed by the product below. <br />
<br />
'''Note:''' All metadata values should be passed as UTF-8 strings.<br><br />
<br />
== Static Measurement ==<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! Key !! Description !! Values !! Required (Obligatory) !! AGF Convention !! Example data - RTL<br />
|-<br />
| assetid || unique ID assigned to each article/page; only characters 0-9, a-z, A-Z underscore and minus are allowed - no special characters or vowel mutations) || custom (no [[Special Characters]]) || ✓ || Content Article ID. If it is not an article page and therefore no ID is available, the page path is used. || "999452"<br />
|-<br />
| section || section of each site (e.g. section value should be first level in page URL: website.com/section) || custom || ✓ || Section of Website or App || "/rtl_portal/news"<br />
|-<br />
| segA || custom segment for reporting: unique values across custom segments (segA + segB + segC) || custom || ✓ || AGOF code or comparable unit code || "dbrsowf_rtlnews"<br />
|-<br />
| segB || custom segment for reporting: unique values across custom segments (segA + segB + segC) || custom || ✓ || Value to define content view count vs. 'Werbetraeger' view count. For Content: "CPI" . For 'Werbetraeger': "WPI_timestamp" (Timestamp in whole seconds, not milliseconds) || For Content: "CPI" . For 'Werbetraeger' after user interaction with the site and newly loaded Content: "WPI_1657634473".<br />
|-<br />
| segC || custom segment for reporting: unique values across custom segments (segA + segB + segC) || custom || || Program name || "IBES"<br />
|-<br />
| subbrand || vcid/sub-brand ID – value is automatically populated through provided App ID. In order to override the sub-brand configured to the App ID, value can be passed here (e.g. multiple sub-brands in App) || provided by Nielsen || ✓ || Same as video measurement, provided by Nielsen || "c01"<br />
|}<br />
<br />
<br />
<br />
== Video Measurement ==<br />
<br />
Please refer to this AGF PDF Document: '''[https://nielsendownloads.digitalengsdk.com/digital/220907_AGF+Custom+Variables+and+Metadata+DCR+SDK++v1.8_english.pdf Metadata Document for Video]'''</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=Radio&diff=5948Radio2022-09-07T19:38:32Z<p>LaMarHolmes: </p>
<hr />
<div>{{Banner|Nielsen Audio Support}}<br />
__NOTOC__<br />
<!-- <br />
{{Alert|<br />
'''October 2020: Product Notification:'''<br><br />
'''''WATERMARK Radio SDK Encoder v1.1.7 with ARM Support is NOW AVAILABLE''''' <br><br />
'''''Official release notification: [https://nielsendownloads.digitalengsdk.com/tv/NLM+WMSDK+Converged+Encoder+5.0.23+Release.pdf Watermark Radio SDK Encoder v1.1.7 ]<br />
'''''}}<br />
--><br />
<!-- --><br />
{| class="wikitable"<br />
|-<br />
! style="width: 50px;" |<br />
! Certified Vendors<br />
|-<br />
| rowspan="1" | <br />
| '''[[Nielsen Radio Certified Vendors]]'''<br />
|-<br />
|}<br />
<br />
== AnaDig 1212 Encoder ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
<br />
| '''AnaDig 1000-1212 Encoder Equipment Manual'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/AnaDig%201212%20Encoder/Equipment%20Manual,%20AnaDig%20Encoder%20(1050-1645%20RevE).pdf Equipment Manual, AnaDig Encoder (1050-1645 RevE)]<br />
<br />
|-<br />
| '''Firmware AnaDig1212 Encoder v1.0.3.1'''<br />
|| {{SmallIcon|ZipIcon.png}} || <br />
* [https://nielsendownloads-blue.digitalengsdk.com/radio/AnaDig%201212%20Encoder/Firmware_AnaDig1212__Encoder_Version_1.0.3.1%20(1096-1284_Rev_A).zip Firmware_AnaDig1212__Encoder_Version_1.0.3.1 (1096-1284_Rev_A)]<br />
|}<br />
<br />
== Analog Encoder ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
<br />
| '''PPM Encoding Best Practices'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Analog%20Encoder/PPM%20Encoding%20Best%20Practices.pdf PPM Encoding Best Practices]<br />
<br />
|-<br />
| '''Analog Encoder Equipment Manual (1050-1473 RevF)'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Analog%20Encoder/Analog%20Encoder%20Equipment%20Manual%20(1050-1473%20RevF).pdf Analog Encoder Equipment Manual (1050-1473 RevF)]<br />
<br />
|}<br />
<br />
== Digital (AES) Encoder ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
| '''Digital (AES) Encoder Equipment Manual (1050-1475 RevF)'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Digital%20(AES)%20Encoder/Digital%20(AES)%20Encoder%20Equipment%20Manual%20(1050-1475%20RevF).pdf Digital (AES) Encoder Equipment Manual (1050-1475 RevF)]<br />
|}<br />
<br />
== Nielsen Audio Software Encoder ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
| '''Nielsen Audio Software Encoder Product Marketing Sheet'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Software%20Encoder/Audio%20Software%20Encoder%20Product%20Marketing%20Sheet%20.pdf Audio Software Encoder Product Marketing Sheet]<br />
|}<br />
<br><br />
<br><br />
<!--<br><br />
<br><br />
<br><br />
--><br />
<!-- --><br />
{{Alert| '''Product Notification:'''<br><br />
'''''MCEM FIRMWARE 1.5.2.07 NOW AVAILABLE''''' <br><br />
'''''Official release notification: [https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel+Encoding+Monitor/Information+Bulletin+206.pdf INFORMATION BULLETIN 206 - RELEASE OF MCEM FIRMWARE 1.5.2.07 ]'''''}}<br />
<br />
== Multi-Channel Encoding Monitor ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
<br />
|-<br />
| '''MCEM 1.5.2.07 Firmware Instructions and New Manual'''<br />
|| {{SmallIcon|ZipIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel+Encoding+Monitor/MCEM+1_5_2_07+Firmware+Instructions+Manual+2022+March+2.zip MCEM 1.5.2.07 Firmware Manual Instructions 2022 March]<br />
<br />
|-<br />
| '''MCEM - Detectability Confidence Spreadsheet History-How to access CSV files'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/Detecability%20Confidence%20One%20Sheeter.pdf Detectability Confidence Spreadsheet History-How to access CSV files]<br />
<br />
|-<br />
| '''MCEM - Encodability View Spreadsheet History-How to access CSV files One-Sheeter'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/Encodability%20One%20Sheeter.pdf Encodability View Spreadsheet History - How to access CSV files]<br />
<br />
|-<br />
| '''MCEM - Data and Analytics One-Sheeter'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20-%20Data%20and%20Analytics%20One-Sheeter.pdf MCEM - Data and Analytics One-Sheeter]<br />
<br />
|-<br />
| '''MCEM - Product Overview'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20-%20Product%20Overview.pdf MCEM - Product Overview]<br />
<br />
|-<br />
| '''MCEM - Quick Reference Guide'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20-%20Quick%20Reference%20Guide.pdf MCEM - Quick Reference Guide]<br />
<br />
|-<br />
| '''MCEM Order Form'''<br />
|| {{SmallIcon|SheetIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20Order%20Form%20e1.xlsx MCEM Order Form]<br />
<br />
|-<br />
| '''MCEM - Instructions for Confirming Connectivity'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://engineeringportal.nielsen.com/w/docs/MCEM-Instructions_for_Confirming_Connectivity.pdf MCEM - Instructions for Confirming Connectivity]<br />
|}<br />
<br />
{| class="wikitable"<br />
|-<br />
!International Audio Documentation<br />
|-<br />
| '''[[International Audio]]'''<br />
|}</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=International_DCR&diff=5947International DCR2022-09-07T16:27:00Z<p>LaMarHolmes: </p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
{{CategoryIcon|International.png|International DCR}}<br />
<br />
__NOTOC__<br />
<br />
<blockquote>Please contact your Nielsen representative for documentation if the guides for your country aren't listed.</blockquote><br />
<br />
{| class="wikitable"<br />
! colspan="5" | Downloads<br />
|-<br />
| style="width: 90px;" |{{SmallIcon|DownloadIcon.png|alt=Cloud API}} <br />
|style="width: 90px;" | {{SmallIcon|SDKIcon.png}}<br />
| '''[[Digital Downloads|SDK Downloads]]'''<br />
|}<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 90px;" | Australia<br />
! style="width: 90px;" |<br />
! style="width: 45px;" | <br />
! style="width: 45px;" | OS<br />
!| Guide<br />
|-<br />
| rowspan="4" | {{SmallIcon|AUFlagIcon.png}}<br />
| rowspan="4" | {{SmallIcon|SDKIcon.png}}<br />
| rowspan="4" | {{OSIcon|VideoIcon.png}}<br />
|-<br />
| {{OSIcon|macOSIcon.png}}<br />
| '''[[DCR Australia Video iOS SDK|Request DCR Australia Video iOS SDK]]'''<br />
|-<br />
| {{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR Australia Video Android SDK|Request DCR Australia Video Android SDK]]'''<br />
|-<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR Australia Video Browser SDK|Request DCR Australia Video Browser SDK]]'''<br />
|}<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 90px;" | Czech<br />
! style="width: 90px;" |<br />
! style="width: 45px;" | <br />
! style="width: 45px;" | OS<br />
!| Guide<br />
|-<br />
| rowspan="6" | {{SmallIcon|CZFlagIcon.png}}<br />
| rowspan="6" | {{SmallIcon|SDKIcon.png}}<br />
| rowspan="2" | {{OSIcon|VideoIcon.png}}<br />
| {{OSIcon|macOSIcon.png}}<br />
<br><br><br />
{{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR Czech Video App SDK]]'''<br />
|-<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR Czech Video Browser SDK]]'''<br />
|-<br />
| rowspan="1" | {{OSIcon|StaticIcon.png}}<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR Czech Static Browser SDK]]'''<br />
|-<br />
| rowspan="3" |<br />
| rowspan="3" |<br />
| '''[[Czech SDK Metadata]]'''<br />
|-<br />
| '''[[Czech Changing Approved Player]]'''<br />
|-<br />
| '''[[Czech Contacts]]'''<br />
|}<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 90px;" | Denmark<br />
! style="width: 90px;" |<br />
! style="width: 45px;" | <br />
! style="width: 45px;" | OS<br />
!| Guide<br />
!| Links<br />
|-<br />
| rowspan="5" | {{SmallIcon|DKFlagIcon.png}}<br />
| rowspan="4" | {{SmallIcon|SDKIcon.png}}<br />
| rowspan="5" | {{OSIcon|VideoIcon.png}}<br />
|-<br />
| {{OSIcon|macOSIcon.png}}<br />
| '''[[DCR Denmark Video iOS SDK]]'''<br />
| [https://engineeringportal.nielsen.com/docs/Special:ClickThrough?region=DK Sign License Agreement]<br />
|-<br />
| {{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR Denmark Video Android SDK]]'''<br />
| [https://engineeringportal.nielsen.com/docs/Special:ClickThrough?region=DK Sign License Agreement]<br />
|-<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR Denmark Video Browser SDK]]'''<br />
| [https://engineeringportal.nielsen.com/docs/Special:ClickThrough?region=DK Sign License Agreement]<br />
|-<br />
| {{SmallIcon|CloudAPIIcon.png}}<br />
| {{OSIcon|APIIcon.png}}<br />
| '''[[DCR Denmark Video Cloud API]]'''<br />
| [https://engineeringportal.nielsen.com/docs/Special:ClickThrough?region=DK Sign License Agreement]<br />
|}<br />
<br />
{| class="wikitable"<br />
! colspan="3" | Germany<br />
|-<br />
| style="width: 90px;" |{{SmallIcon|DEFlagIcon.png}} <br />
|style="width: 90px;" | {{SmallIcon|SDKIcon.png}}<br />
| '''[[AGF Implementation Documentation]]'''<br />
|}<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 90px;" | Ireland<br />
! style="width: 90px;" |<br />
! style="width: 45px;" | <br />
! style="width: 45px;" | OS<br />
!| Guide<br />
!| Links<br />
|-<br />
| rowspan="4" | {{SmallIcon|IEflagicon.png}}<br />
| rowspan="4" | {{SmallIcon|SDKIcon.png}}<br />
| rowspan="4" | {{OSIcon|VideoIcon.png}}<br />
|-<br />
| {{OSIcon|macOSIcon.png}}<br />
| '''[[DCR Ireland Video iOS SDK]]'''<br />
| [https://engineeringportal.nielsen.com/w/IRL/ Download IRL iOS SDK]<br />
|-<br />
| {{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR Ireland Video Android SDK]]'''<br />
| [https://engineeringportal.nielsen.com/w/IRL/ Download IRL Android SDK]<br />
|-<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR Ireland Video Browser SDK]]'''<br />
| [https://engineeringportal.nielsen.com/w/IRL/ Download IRL Browser SDK]<br />
|}<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 90px;" | Italy<br />
! style="width: 90px;" |<br />
! style="width: 45px;" | <br />
! style="width: 45px;" | OS<br />
!| Guide<br />
|-<br />
| rowspan="9" | {{SmallIcon|ITFlagIcon.png}}<br />
| rowspan="9" | {{SmallIcon|SDKIcon.png}}<br />
| rowspan="3" | {{OSIcon|VideoIcon.png}}<br />
|{{OSIcon|macOSIcon.png}}<br />
| '''[[DCR Italy Video iOS SDK]]'''<br />
|-<br />
|{{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR Italy Video Android SDK]]'''<br />
|-<br />
| rowspan="1" | {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR Italy Video Browser SDK (6.0.0)]]'''<br />
|-<br />
| rowspan="5" | {{OSIcon|StaticIcon.png}}<br />
|{{OSIcon|macOSIcon.png}}<br />
| '''[[DCR Italy Static iOS SDK]]'''<br />
|-<br />
|{{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR Italy Static Android SDK]]'''<br />
|-<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR Italy Static Browser SDK]]'''<br />
|-<br />
| {{OSIcon|FacebookIcon.png|alt=Facebook Instant Articles}}<br />
| '''[[DCR Italy Static Facebook Instant Articles Browser SDK]]'''<br />
|-<br />
| {{OSIcon|AMPIcon.png|alt=Google AMP}}<br />
| '''[[DCR Italy Static Google AMP Cloud API]]'''<br />
|}<br />
{| class="wikitable"<br />
|-<br />
! style="width: 90px;" | KSA<br />
! style="width: 90px;" |<br />
! style="width: 45px;" | <br />
! style="width: 45px;" | OS<br />
!| Guide<br />
|-<br />
| rowspan="3" | {{SmallIcon|Saudi Arabia.png}} <br />
| rowspan="3" | {{SmallIcon|SDKIcon.png}}<br />
| rowspan="3" | {{OSIcon|VideoIcon.png}}<br />
| {{OSIcon|macOSIcon.png}}<br />
| '''[[DCR KSA Video iOS SDK]]'''<br />
|-<br />
| {{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR KSA Video Android SDK]]'''<br />
|-<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR KSA Video Browser SDK]]'''<br />
|}<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 90px;" | Norway<br />
! style="width: 90px;" |<br />
! style="width: 45px;" | <br />
! style="width: 45px;" | OS<br />
!| Guide<br />
|-<br />
| rowspan="3" | {{SmallIcon|norway-flag-xs.png}}<br />
| rowspan="3" | {{SmallIcon|SDKIcon.png}}<br />
| rowspan="3" | {{OSIcon|VideoIcon.png}}<br />
| {{OSIcon|macOSIcon.png}}<br />
| '''[[DCR Norway Audio ios App SDK]]'''<br />
|-<br />
| {{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR Norway Audio Android App SDK]]'''<br />
|-<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR Norway Audio Browser SDK]]'''<br />
|}<br />
<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 90px;" | Poland<br />
! style="width: 90px;" |<br />
! style="width: 45px;" | <br />
! style="width: 45px;" | OS<br />
!| Guide<br />
|-<br />
| rowspan="3" | {{SmallIcon|PLFlagIcon.png}}<br />
| rowspan="3" | {{SmallIcon|SDKIcon.png}}<br />
| rowspan="3" | {{OSIcon|VideoIcon.png}}<br />
| {{OSIcon|macOSIcon.png}}<br />
| '''[[DCR Poland Video iOS SDK]]'''<br />
|-<br />
| {{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR Poland Video Android SDK]]'''<br />
|-<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR Poland Video Browser SDK]]'''<br />
|}<br />
<br />
<!--<br />
{| class="wikitable"<br />
|-<br />
! style="width: 90px;" | India<br />
! style="width: 90px;" |<br />
! style="width: 45px;" | <br />
! style="width: 45px;" | OS<br />
!| Guide<br />
|-<br />
| rowspan="4" | {{SmallIcon|INFlagIcon.png}}<br />
| rowspan="4" | {{SmallIcon|SDKIcon.png}}<br />
| rowspan="4" | {{OSIcon|VideoIcon.png}}<br />
|-<br />
| {{OSIcon|macOSIcon.png}}<br />
| '''[[DCR India Video iOS SDK]]'''<br />
|-<br />
| {{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR India Video Android SDK]]'''<br />
|-<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR India Video Browser SDK]]'''<br />
|}<br />
--><br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 90px;" | Sweden<br />
! style="width: 90px;" |<br />
! style="width: 45px;" | <br />
! style="width: 45px;" | OS<br />
!| Guide<br />
!| Links<br />
|-<br />
| rowspan="5" | {{SmallIcon|SWflagicon.png}}<br />
| rowspan="4" | {{SmallIcon|SDKIcon.png}}<br />
| rowspan="5" | {{OSIcon|VideoIcon.png}}<br />
|-<br />
| {{OSIcon|macOSIcon.png}}<br />
| '''[[DCR Sweden Video iOS SDK]]'''<br />
| [https://engineeringportal.nielsen.com/docs/Special:ClickThrough?region=SE Sign License Agreement]<br />
|-<br />
| {{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR Sweden Video Android SDK]]'''<br />
| [https://engineeringportal.nielsen.com/docs/Special:ClickThrough?region=SE Sign License Agreement]<br />
|-<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR Sweden Video Browser SDK]]'''<br />
| [https://engineeringportal.nielsen.com/docs/Special:ClickThrough?region=SE Sign License Agreement]<br />
|-<br />
| {{SmallIcon|CloudAPIIcon.png}}<br />
| {{OSIcon|APIIcon.png}}<br />
| '''[[DCR Sweden Video Cloud API]]'''<br />
| [https://engineeringportal.nielsen.com/docs/Special:ClickThrough?region=SE Sign License Agreement]<br />
|}<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 90px;" | Taiwan<br />
! style="width: 90px;" |<br />
! style="width: 45px;" | <br />
! style="width: 45px;" | OS<br />
!| Guide<br />
|-<br />
| rowspan="3" | {{SmallIcon|TWFlagIcon.png}}<br />
| rowspan="3" | {{SmallIcon|SDKIcon.png}}<br />
| rowspan="3" | {{OSIcon|VideoIcon.png}}<br />
| {{OSIcon|macOSIcon.png}}<br />
| '''[[DCR Taiwan Video iOS SDK]]'''<br />
|-<br />
| {{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR Taiwan Video Android SDK]]'''<br />
|-<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR Taiwan Video Browser SDK]]'''<br />
|}<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 90px;" | Thailand<br />
! style="width: 90px;" |<br />
! style="width: 45px;" | <br />
! style="width: 45px;" | OS<br />
!| Guide<br />
|-<br />
| rowspan="3" | {{SmallIcon|THFlagIcon.png}}<br />
| rowspan="3" | {{SmallIcon|SDKIcon.png}}<br />
| rowspan="3" | {{OSIcon|VideoIcon.png}}<br />
| {{OSIcon|macOSIcon.png}}<br />
| '''[[DCR Thailand Video iOS SDK]]'''<br />
|-<br />
| {{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR Thailand Video Android SDK]]'''<br />
|-<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR Thailand Video Browser SDK]]'''<br />
|}</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=Radio&diff=5946Radio2022-09-07T16:20:06Z<p>LaMarHolmes: </p>
<hr />
<div>{{Banner|Nielsen Audio Support}}<br />
__NOTOC__<br />
<!-- <br />
{{Alert|<br />
'''October 2020: Product Notification:'''<br><br />
'''''WATERMARK Radio SDK Encoder v1.1.7 with ARM Support is NOW AVAILABLE''''' <br><br />
'''''Official release notification: [https://nielsendownloads.digitalengsdk.com/tv/NLM+WMSDK+Converged+Encoder+5.0.23+Release.pdf Watermark Radio SDK Encoder v1.1.7 ]<br />
'''''}}<br />
--><br />
<!-- --><br />
{| class="wikitable"<br />
|-<br />
! style="width: 50px;" |<br />
! Certified Vendors<br />
|-<br />
| rowspan="1" | <br />
| '''[[Nielsen Radio Certified Vendors]]'''<br />
|-<br />
|}<br />
<br />
== AnaDig 1212 Encoder ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
<br />
| '''AnaDig 1000-1212 Encoder Equipment Manual'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/AnaDig%201212%20Encoder/Equipment%20Manual,%20AnaDig%20Encoder%20(1050-1645%20RevE).pdf Equipment Manual, AnaDig Encoder (1050-1645 RevE)]<br />
<br />
|-<br />
| '''Firmware AnaDig1212 Encoder v1.0.3.1'''<br />
|| {{SmallIcon|ZipIcon.png}} || <br />
* [https://nielsendownloads-blue.digitalengsdk.com/radio/AnaDig%201212%20Encoder/Firmware_AnaDig1212__Encoder_Version_1.0.3.1%20(1096-1284_Rev_A).zip Firmware_AnaDig1212__Encoder_Version_1.0.3.1 (1096-1284_Rev_A)]<br />
|}<br />
<br />
== Analog Encoder ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
<br />
| '''PPM Encoding Best Practices'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Analog%20Encoder/PPM%20Encoding%20Best%20Practices.pdf PPM Encoding Best Practices]<br />
<br />
|-<br />
| '''Analog Encoder Equipment Manual (1050-1473 RevF)'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Analog%20Encoder/Analog%20Encoder%20Equipment%20Manual%20(1050-1473%20RevF).pdf Analog Encoder Equipment Manual (1050-1473 RevF)]<br />
<br />
|}<br />
<br />
== Digital (AES) Encoder ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
| '''Digital (AES) Encoder Equipment Manual (1050-1475 RevF)'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Digital%20(AES)%20Encoder/Digital%20(AES)%20Encoder%20Equipment%20Manual%20(1050-1475%20RevF).pdf Digital (AES) Encoder Equipment Manual (1050-1475 RevF)]<br />
|}<br />
<br />
== Nielsen Audio Software Encoder ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
| '''Nielsen Audio Software Encoder Product Marketing Sheet'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Software%20Encoder/Audio%20Software%20Encoder%20Product%20Marketing%20Sheet%20.pdf Audio Software Encoder Product Marketing Sheet]<br />
|}<br />
<br><br />
<br><br />
<!--<br><br />
<br><br />
<br><br />
--><br />
<!-- --><br />
{{Alert| '''Product Notification:'''<br><br />
'''''MCEM FIRMWARE 1.5.2.07 NOW AVAILABLE''''' <br><br />
'''''Official release notification: [https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel+Encoding+Monitor/Information+Bulletin+206.pdf INFORMATION BULLETIN 206 - RELEASE OF MCEM FIRMWARE 1.5.2.07 ]'''''}}<br />
<br />
== Multi-Channel Encoding Monitor ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
<br />
|-<br />
| '''MCEM 1.5.2.07 Firmware Instructions and New Manual'''<br />
|| {{SmallIcon|ZipIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel+Encoding+Monitor/MCEM+1_5_2_07+Firmware+Instructions+Manual+2022+March+2.zip MCEM 1.5.2.07 Firmware Manual Instructions 2022 March]<br />
<br />
|-<br />
| '''MCEM - Detectability Confidence Spreadsheet History-How to access CSV files'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/Detecability%20Confidence%20One%20Sheeter.pdf Detectability Confidence Spreadsheet History-How to access CSV files]<br />
<br />
|-<br />
| '''MCEM - Encodability View Spreadsheet History-How to access CSV files One-Sheeter'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/Encodability%20One%20Sheeter.pdf Encodability View Spreadsheet History - How to access CSV files]<br />
<br />
|-<br />
| '''MCEM - Data and Analytics One-Sheeter'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20-%20Data%20and%20Analytics%20One-Sheeter.pdf MCEM - Data and Analytics One-Sheeter]<br />
<br />
|-<br />
| '''MCEM - Product Overview'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20-%20Product%20Overview.pdf MCEM - Product Overview]<br />
<br />
|-<br />
| '''MCEM - Quick Reference Guide'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20-%20Quick%20Reference%20Guide.pdf MCEM - Quick Reference Guide]<br />
<br />
|-<br />
| '''MCEM Order Form'''<br />
|| {{SmallIcon|SheetIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20Order%20Form%20e1.xlsx MCEM Order Form]<br />
|}<br />
<br />
{| class="wikitable"<br />
|-<br />
!International Audio Documentation<br />
|-<br />
| '''[[International Audio]]'''<br />
|}</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=International_Audio&diff=5945International Audio2022-09-07T16:18:30Z<p>LaMarHolmes: Created page with "{{Breadcrumb|}} {{Breadcrumb|Radio}} {{CurrentBreadcrumb}} {{CategoryIcon|International.png|International Audio}} __NOTOC__ <blockquote>Please contact your Nielsen represent..."</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Radio}} {{CurrentBreadcrumb}}<br />
{{CategoryIcon|International.png|International Audio}}<br />
<br />
__NOTOC__<br />
<br />
<blockquote>Please contact your Nielsen representative for documentation if the guides for your country aren't listed.</blockquote><br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 90px;" | Italy<br />
! style="width: 90px;" |<br />
! style="width: 45px;" | <br />
! style="width: 45px;" | OS<br />
!| Guide<br />
|-<br />
| rowspan="4" |{{SmallIcon|ITFlagIcon.png}}<br />
| rowspan="4" |{{SmallIcon|SDKIcon.png}}<br />
| rowspan="3" | {{OSIcon|VideoIcon.png}}<br />
|{{OSIcon|macOSIcon.png}}<br />
| '''[[DCR Italy AUDIO iOS SDK]]'''<br />
|-<br />
|{{OSIcon|AndroidIcon.png}}<br />
| '''[[DCR Italy AUDIO Android SDK]]'''<br />
|-<br />
| {{OSIcon|BrowserIcon.png}}<br />
| '''[[DCR Italy AUDIO Browser SDK]]''' <br />
|}</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=Radio&diff=5944Radio2022-09-07T16:17:45Z<p>LaMarHolmes: </p>
<hr />
<div>{{Banner|Nielsen Audio Support}}<br />
__NOTOC__<br />
<!-- <br />
{{Alert|<br />
'''October 2020: Product Notification:'''<br><br />
'''''WATERMARK Radio SDK Encoder v1.1.7 with ARM Support is NOW AVAILABLE''''' <br><br />
'''''Official release notification: [https://nielsendownloads.digitalengsdk.com/tv/NLM+WMSDK+Converged+Encoder+5.0.23+Release.pdf Watermark Radio SDK Encoder v1.1.7 ]<br />
'''''}}<br />
--><br />
<!-- --><br />
{| class="wikitable"<br />
|-<br />
! style="width: 50px;" |<br />
! Certified Vendors<br />
|-<br />
| rowspan="1" | <br />
| '''[[Nielsen Radio Certified Vendors]]'''<br />
|-<br />
|}<br />
<br />
== AnaDig 1212 Encoder ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
<br />
| '''AnaDig 1000-1212 Encoder Equipment Manual'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/AnaDig%201212%20Encoder/Equipment%20Manual,%20AnaDig%20Encoder%20(1050-1645%20RevE).pdf Equipment Manual, AnaDig Encoder (1050-1645 RevE)]<br />
<br />
|-<br />
| '''Firmware AnaDig1212 Encoder v1.0.3.1'''<br />
|| {{SmallIcon|ZipIcon.png}} || <br />
* [https://nielsendownloads-blue.digitalengsdk.com/radio/AnaDig%201212%20Encoder/Firmware_AnaDig1212__Encoder_Version_1.0.3.1%20(1096-1284_Rev_A).zip Firmware_AnaDig1212__Encoder_Version_1.0.3.1 (1096-1284_Rev_A)]<br />
|}<br />
<br />
== Analog Encoder ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
<br />
| '''PPM Encoding Best Practices'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Analog%20Encoder/PPM%20Encoding%20Best%20Practices.pdf PPM Encoding Best Practices]<br />
<br />
|-<br />
| '''Analog Encoder Equipment Manual (1050-1473 RevF)'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Analog%20Encoder/Analog%20Encoder%20Equipment%20Manual%20(1050-1473%20RevF).pdf Analog Encoder Equipment Manual (1050-1473 RevF)]<br />
<br />
|}<br />
<br />
== Digital (AES) Encoder ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
| '''Digital (AES) Encoder Equipment Manual (1050-1475 RevF)'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Digital%20(AES)%20Encoder/Digital%20(AES)%20Encoder%20Equipment%20Manual%20(1050-1475%20RevF).pdf Digital (AES) Encoder Equipment Manual (1050-1475 RevF)]<br />
|}<br />
<br />
== Nielsen Audio Software Encoder ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
|-<br />
| '''Nielsen Audio Software Encoder Product Marketing Sheet'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Software%20Encoder/Audio%20Software%20Encoder%20Product%20Marketing%20Sheet%20.pdf Audio Software Encoder Product Marketing Sheet]<br />
|}<br />
<br><br />
<br><br />
<!--<br><br />
<br><br />
<br><br />
--><br />
<!-- --><br />
{{Alert| '''Product Notification:'''<br><br />
'''''MCEM FIRMWARE 1.5.2.07 NOW AVAILABLE''''' <br><br />
'''''Official release notification: [https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel+Encoding+Monitor/Information+Bulletin+206.pdf INFORMATION BULLETIN 206 - RELEASE OF MCEM FIRMWARE 1.5.2.07 ]'''''}}<br />
<br />
== Multi-Channel Encoding Monitor ==<br />
{| class="wikitable"<br />
|-<br />
! style="width: 375px;" | Description<br />
! style="width: 75px;" | File <br />
! Download <br />
<br />
|-<br />
| '''MCEM 1.5.2.07 Firmware Instructions and New Manual'''<br />
|| {{SmallIcon|ZipIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel+Encoding+Monitor/MCEM+1_5_2_07+Firmware+Instructions+Manual+2022+March+2.zip MCEM 1.5.2.07 Firmware Manual Instructions 2022 March]<br />
<br />
|-<br />
| '''MCEM - Detectability Confidence Spreadsheet History-How to access CSV files'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/Detecability%20Confidence%20One%20Sheeter.pdf Detectability Confidence Spreadsheet History-How to access CSV files]<br />
<br />
|-<br />
| '''MCEM - Encodability View Spreadsheet History-How to access CSV files One-Sheeter'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/Encodability%20One%20Sheeter.pdf Encodability View Spreadsheet History - How to access CSV files]<br />
<br />
|-<br />
| '''MCEM - Data and Analytics One-Sheeter'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20-%20Data%20and%20Analytics%20One-Sheeter.pdf MCEM - Data and Analytics One-Sheeter]<br />
<br />
|-<br />
| '''MCEM - Product Overview'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20-%20Product%20Overview.pdf MCEM - Product Overview]<br />
<br />
|-<br />
| '''MCEM - Quick Reference Guide'''<br />
|| {{SmallIcon|PDFIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20-%20Quick%20Reference%20Guide.pdf MCEM - Quick Reference Guide]<br />
<br />
|-<br />
| '''MCEM Order Form'''<br />
|| {{SmallIcon|SheetIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/radio/Multi-Channel%20Encoding%20Monitor/MCEM%20Order%20Form%20e1.xlsx MCEM Order Form]<br />
|}<br />
<br />
{| class="wikitable"<br />
|-<br />
!International Audio Documentation<br />
|-<br />
| '''[[International_Audio|International Audio]]'''<br />
|}</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=iOS_SDK_App_Privacy&diff=5806iOS SDK App Privacy2022-05-12T21:50:20Z<p>LaMarHolmes: /* Types of Data */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
= User Privacy and Data Use =<br />
<blockquote><br />
This document is Nielsen Confidential Information and subject to the confidentiality agreements in place between Nielsen and your organization. The information is provided as-is and for general informational purposes only. You are responsible for your own compliance with any laws, regulations or any Apple policies. Please refer to your agreements with Nielsen as necessary. <br />
<br />
Contact: privacy.department@nielsen.com<br>Last Updated: 3rd February, 2021<br>Version: 1</blockquote><br />
__NOTOC__<br />
As of December 8th, 2020 Apple is requiring that any new apps submitted to the App Store complete an updated submission process that requests information about an app’s privacy practices, including the practices of third-parties whose code may be integrated into an app. <br />
<br />
Please refer to Apple’s developer site for more details: https://developer.apple.com/app-store/app-privacy-details/<br />
<br />
Nielsen has put together this document to make information about Nielsen’s data collection practices available to clients who use the Nielsen Digital SDK and Nielsen tags. <br />
<br />
The document is organized using headings of the [https://developer.apple.com/app-store/app-privacy-details/ App privacy details on the App Store] (as of December 7th, 2020) webpage for convenience.<br />
<br />
= Answering app privacy questions =<br />
* '''Important: This information is provided for convenience only and is only applicable to the Nielsen Digital SDK and/or the Nielsen tag.'''<br />
* '''Clients are responsible for their own apps and their own submissions to the app store.''' <br />
* Please refer to [https://www.nielsen.com/us/en/legal/privacy-statement/digital-measurement/ Nielsen’s Privacy Statement for Digital Measurement] if you would like more information about Nielsen’s data collection practices.<br />
<br />
== Data Collection ==<br />
Nielsen as a third-party, provides analytics based reporting services to publisher clients.<br />
<br />
== Optional Disclosure ==<br />
Publisher clients collect and pass data to Nielsen for the purpose of advertising measurement and content measurement. <br />
<br />
== Types of Data ==<br />
Per the list of data items presented to the publisher during the App certification process on https://developer.apple.com/app-store/app-privacy-details/, the following table discloses those data items that Nielsen requests publisher Apps pass to Nielsen.<br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold; text-align:center; "<br />
! Data Type Name<br />
! style="text-align:center; "| Collected by<br> Nielsen Digital?<br />
! Notes<br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Contact Info<br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Name<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Email Address<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Phone Number<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Physical Address<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Other User Contact Info<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Health & Fitness<br />
|-<br />
| style="color:#222;" | Health<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="color:#222;" | Fitness<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Financial Info<br />
|-<br />
| style="color:#222;" | Payment Info<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="color:#222;" | Credit Info<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="color:#222;" | Other Financial Info<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Location<br />
|-<br />
| style="color:#222;" | Precise Location<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="color:#222;" | Coarse Location<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Sensitive Info<br />
|-<br />
| style="color:#222;" | Sensitive Info<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Contacts<br />
|-<br />
| style="color:#222;" | Contacts<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | User Content<br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Emails or Text Messages<br />
| style="text-align:center; color:#222;" | Yes (Hashed Emails)/ No (Text Messages)<br />
| Please work with your Nielsen Technical Account Manager if choosing to append this hashed information to DAR Tag<br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Photos or Videos<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Audio Data<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Gameplay Content<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Customer Support<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Other User Content<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Browsing History<br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Browsing History<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Search History<br />
|-<br />
| style="color:#222;" | Search History<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Identifiers<br />
|-<br />
| style="color:#222;" | User ID<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-weight:bold; color:#222;"<br />
| style="font-weight:normal;" | Device ID<br />
| style="text-align:center;" | Yes<br />
| Advertiser ID / IDFA, IDFV<br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Purchases<br />
|-<br />
| style="color:#222;" | Purchase History<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Usage Data<br />
|- style="font-weight:bold; color:#222;"<br />
| style="font-weight:normal;" | Product Interaction<br />
| style="text-align:center;" | Yes<br />
| Private, publisher encoded metadata<br /> representing video content (Program, Episode, Genre, …),<br /> video playback start time, video playback end time<br />
|- style="font-weight:bold; color:#222;"<br />
| style="font-weight:normal;" | Advertising Data<br />
| style="text-align:center;" | Yes<br />
| Publisher / advertiser encoded metadata <br />representing an advertising creative<br />
|- style="font-weight:bold; color:#222;"<br />
| style="font-weight:normal;" | Other Usage Data<br />
| style="text-align:center;" | Yes<br />
| IP Address, User Agent, <br />Nielsen Identifier, Limited Ad Tracking status<br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Diagnostics<br />
|-<br />
| style="color:#222;" | Crash Data<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="color:#222;" | Performance Data<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="color:#222;" | Other Diagnostic Data<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|}<br />
<br />
== Data Use ==<br />
The Data Types identified above as collected by the Nielsen Digital SDK/Nielsen tag are used to measure audience size. The collection of this data enables the creation of research insights, including the composition of the audience in aggregate by age & gender demographics that viewed a piece of content and / or ad creative.<br />
<br />
Tools and methods are used to make sure that there is no reasonable possibility of identifying users from the reports and insights created. The data types identified above as collected are combined with data collected from other sources to produce aggregate reports from which individual users or personal information cannot be identified; if it is not aggregated, we take steps to make sure that there is no reasonable possibility of re-identification.<br />
<br />
== Data linked to the user ==<br />
Data may be matched with data collected from Nielsen panelists or other companies that recognize their own users or that collect data about consumers generally. When the data we collect is combined with the data collected from other sources it is used to produce aggregated reports from which users cannot be uniquely identified; if it is not aggregated, we take steps to make sure there is no reasonable possibility of re-identification.<br />
<br />
== Tracking ==<br />
Nielsen uses Device ID (Data Type Name) during the process of measuring audience size. Please see the Data Use section above for more detail.<br />
<br />
== Privacy Links ==<br />
Nielsen’s Privacy Statement for Digital Measurement can be found here: [https://www.nielsen.com/us/en/legal/privacy-statement/digital-measurement/ Digital Measurement Privacy Statement – Nielsen]<br />
<br />
If you wish to embed a link to Nielsen’s Privacy Statement then please contact Nielsen client service for more further guidance.<br />
<br />
<blockquote><br />
This document is Nielsen Confidential Information and subject to the confidentiality agreements in place between Nielsen and your organization. The information is provided as-is and for general informational purposes only. You are responsible for your own compliance with any laws, regulations or any Apple policies. Please refer to your agreements with Nielsen as necessary. <br />
</blockquote></div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=iOS_SDK_App_Privacy&diff=5805iOS SDK App Privacy2022-05-12T21:48:47Z<p>LaMarHolmes: /* Types of Data */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
= User Privacy and Data Use =<br />
<blockquote><br />
This document is Nielsen Confidential Information and subject to the confidentiality agreements in place between Nielsen and your organization. The information is provided as-is and for general informational purposes only. You are responsible for your own compliance with any laws, regulations or any Apple policies. Please refer to your agreements with Nielsen as necessary. <br />
<br />
Contact: privacy.department@nielsen.com<br>Last Updated: 3rd February, 2021<br>Version: 1</blockquote><br />
__NOTOC__<br />
As of December 8th, 2020 Apple is requiring that any new apps submitted to the App Store complete an updated submission process that requests information about an app’s privacy practices, including the practices of third-parties whose code may be integrated into an app. <br />
<br />
Please refer to Apple’s developer site for more details: https://developer.apple.com/app-store/app-privacy-details/<br />
<br />
Nielsen has put together this document to make information about Nielsen’s data collection practices available to clients who use the Nielsen Digital SDK and Nielsen tags. <br />
<br />
The document is organized using headings of the [https://developer.apple.com/app-store/app-privacy-details/ App privacy details on the App Store] (as of December 7th, 2020) webpage for convenience.<br />
<br />
= Answering app privacy questions =<br />
* '''Important: This information is provided for convenience only and is only applicable to the Nielsen Digital SDK and/or the Nielsen tag.'''<br />
* '''Clients are responsible for their own apps and their own submissions to the app store.''' <br />
* Please refer to [https://www.nielsen.com/us/en/legal/privacy-statement/digital-measurement/ Nielsen’s Privacy Statement for Digital Measurement] if you would like more information about Nielsen’s data collection practices.<br />
<br />
== Data Collection ==<br />
Nielsen as a third-party, provides analytics based reporting services to publisher clients.<br />
<br />
== Optional Disclosure ==<br />
Publisher clients collect and pass data to Nielsen for the purpose of advertising measurement and content measurement. <br />
<br />
== Types of Data ==<br />
Per the list of data items presented to the publisher during the App certification process on https://developer.apple.com/app-store/app-privacy-details/, the following table discloses those data items that Nielsen requests publisher Apps pass to Nielsen.<br />
<br />
{| class="wikitable" <br />
|- style="font-weight:bold; text-align:center; "<br />
! Data Type Name<br />
! style="text-align:center; "| Collected by<br> Nielsen Digital?<br />
! Notes<br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Contact Info<br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Name<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Email Address<br />
| style="text-align:center; color:#222;" | Yes (Hashed Emails)<br />
| Please work with your Nielsen Technical Account Manager if choosing to append this hashed information to DAR Tag<br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Phone Number<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Physical Address<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Other User Contact Info<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Health & Fitness<br />
|-<br />
| style="color:#222;" | Health<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="color:#222;" | Fitness<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Financial Info<br />
|-<br />
| style="color:#222;" | Payment Info<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="color:#222;" | Credit Info<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="color:#222;" | Other Financial Info<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Location<br />
|-<br />
| style="color:#222;" | Precise Location<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="color:#222;" | Coarse Location<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Sensitive Info<br />
|-<br />
| style="color:#222;" | Sensitive Info<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Contacts<br />
|-<br />
| style="color:#222;" | Contacts<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | User Content<br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Emails or Text Messages<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Photos or Videos<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Audio Data<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Gameplay Content<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Customer Support<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Other User Content<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Browsing History<br />
|-<br />
| style="background-color:#FFF; color:#1D1D1F;" | Browsing History<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Search History<br />
|-<br />
| style="color:#222;" | Search History<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Identifiers<br />
|-<br />
| style="color:#222;" | User ID<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-weight:bold; color:#222;"<br />
| style="font-weight:normal;" | Device ID<br />
| style="text-align:center;" | Yes<br />
| Advertiser ID / IDFA, IDFV<br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Purchases<br />
|-<br />
| style="color:#222;" | Purchase History<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Usage Data<br />
|- style="font-weight:bold; color:#222;"<br />
| style="font-weight:normal;" | Product Interaction<br />
| style="text-align:center;" | Yes<br />
| Private, publisher encoded metadata<br /> representing video content (Program, Episode, Genre, …),<br /> video playback start time, video playback end time<br />
|- style="font-weight:bold; color:#222;"<br />
| style="font-weight:normal;" | Advertising Data<br />
| style="text-align:center;" | Yes<br />
| Publisher / advertiser encoded metadata <br />representing an advertising creative<br />
|- style="font-weight:bold; color:#222;"<br />
| style="font-weight:normal;" | Other Usage Data<br />
| style="text-align:center;" | Yes<br />
| IP Address, User Agent, <br />Nielsen Identifier, Limited Ad Tracking status<br />
|- style="font-style:italic; font-weight:bold; background-color:#EFEFEF; color:#222;"<br />
| colspan="3" | Diagnostics<br />
|-<br />
| style="color:#222;" | Crash Data<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="color:#222;" | Performance Data<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|-<br />
| style="color:#222;" | Other Diagnostic Data<br />
| style="text-align:center; color:#222;" | No<br />
| <br />
|}<br />
<br />
== Data Use ==<br />
The Data Types identified above as collected by the Nielsen Digital SDK/Nielsen tag are used to measure audience size. The collection of this data enables the creation of research insights, including the composition of the audience in aggregate by age & gender demographics that viewed a piece of content and / or ad creative.<br />
<br />
Tools and methods are used to make sure that there is no reasonable possibility of identifying users from the reports and insights created. The data types identified above as collected are combined with data collected from other sources to produce aggregate reports from which individual users or personal information cannot be identified; if it is not aggregated, we take steps to make sure that there is no reasonable possibility of re-identification.<br />
<br />
== Data linked to the user ==<br />
Data may be matched with data collected from Nielsen panelists or other companies that recognize their own users or that collect data about consumers generally. When the data we collect is combined with the data collected from other sources it is used to produce aggregated reports from which users cannot be uniquely identified; if it is not aggregated, we take steps to make sure there is no reasonable possibility of re-identification.<br />
<br />
== Tracking ==<br />
Nielsen uses Device ID (Data Type Name) during the process of measuring audience size. Please see the Data Use section above for more detail.<br />
<br />
== Privacy Links ==<br />
Nielsen’s Privacy Statement for Digital Measurement can be found here: [https://www.nielsen.com/us/en/legal/privacy-statement/digital-measurement/ Digital Measurement Privacy Statement – Nielsen]<br />
<br />
If you wish to embed a link to Nielsen’s Privacy Statement then please contact Nielsen client service for more further guidance.<br />
<br />
<blockquote><br />
This document is Nielsen Confidential Information and subject to the confidentiality agreements in place between Nielsen and your organization. The information is provided as-is and for general informational purposes only. You are responsible for your own compliance with any laws, regulations or any Apple policies. Please refer to your agreements with Nielsen as necessary. <br />
</blockquote></div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DAR_Tag_Implementation_Guide&diff=5714DAR Tag Implementation Guide2022-03-18T16:12:56Z<p>LaMarHolmes: /* HEM Support (Hashed Email) */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
== Introduction ==<br />
<br />
Nielsen Digital Ad Ratings is a measurement platform for online advertising campaigns. The platform provides a clear view of the true audience of a campaign, including '''Reach''', '''Frequency''', and '''GRP''' statistics by audience demographic group.<br />
<br />
The key innovation of the platform is the inclusion of demographic data from leading web publishers, including Facebook, to attach actual user demographics to ad impressions.<br />
<br />
The diagram below summarizes how the Nielsen tag measures the ad campaign:<br />
# Advertiser places ads on one or more websites<br />
#Website displays ad to a user<br />
#Nielsen tag counts impressions and controls redirect to the Data Enrichment Provider<br />
[[File:dar-image2.png|900px]]<br />
<br />
<br />
=== Support for Other Nielsen Ad Effectiveness Products ===<br />
<br />
The tag used for Nielsen Digital Ad Ratings is compatible for all Nielsen Ad Effectiveness products, including (but not limited to) Brand Effect Extended View, Response Effect, and Sales Effect.<br />
<br />
=== User Experience ===<br />
<br />
The tags described in this document are used only to measure audience exposure to advertisements; they do not launch a survey, and have no impact on the user experience. Typical response time for the tag is on par with industry standards and because the code executed is simple and fires after the ad loads, they are transparent to the user.<br />
<br />
For further information on survey-based products, or any other products, please contact your Client Services Manager.<br />
__TOC__<br />
== Available Tag Versions ==<br />
<br />
The Nielsen Digital Ad Ratings system offers three basic types of ad tags<br />
<br />
* '''Pixel Tag'''<br />
This is the simplest version of the tag, generally for use by clients who cannot accept JavaScript format tags or have limited options for implementation. It includes encryption, but does not utilize referrer masking.<br />
<br />
* '''JavaScript Display Tag'''<br />
This tag provides impression measurement similar to the pixel tag, but in addition also performs Viewability measurement. It uses Nielsen's proprietary methods to investigate the ad slot and measure ad viewability and can also utilize an existing OM SDK integration for measurement and reporting. It works in web contexts and in-app ad containers.<br />
<br />
* '''JavaScript Video Tags''' <br />
Nielsen's video tag can be utilized via our vWrap service and can be used in both VPAID and OMID environments. It supports OMID in-app and OM Web integrations and provides impression and viewability measurement. For VPAID, it can either wrap an existing VPAID player or can act as its own VPAID ad unit with the MP4s in the VAST file.<br />
<br />
The JavaScript versions are recommended because they provide the highest level of confidentiality by masking the source of the ad from being viewable by Data Providers. Some situations may not afford use of JavaScript and in those cases, the pixel version will be recommended. Note that in many cases the referrer is cast as the ad server due to the nature of being served inside iframes, so the “masking” here is extraneous.<br />
<br />
=== Tag Examples ===<br />
<br />
<br><br />
'''IMAGE Pixel Tag''' (Static example)<br />
<syntaxhighlight lang="javascript"><br />
<img src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3&ca=cmpXXXX&cr=&pc=plcXXXX&r=[timestamp]"<br />
width="1" height="1" alt=""/><br />
</syntaxhighlight><br />
<br />
'''IMAGE Pixel Tag''' (Macro example)<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"><br />
</script><br />
</syntaxhighlight><br />
<br />
'''JavaScript Display Tag'''<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript" <br />
src="https://dar.imrworldwide.com/js/dar.js?ca=%ebuy!&cr=%ecid!&ce=PUBLISHER.ID&ci=nlsnciXXXX&pc=%epid!&am=3<br />
"></script><br />
</syntaxhighlight><br />
<br />
'''JavaScript Video Tag vWrap URL'''<br />
<syntaxhighlight lang="html"><br />
https://vwrap.imrworldwide.com/v1/wrap?ca=nlsnxxxxxx&cr=AD.ID&ce=PUBLISHER.ID&<br />
pc=PLACEMENT.ID&ci=nlsncixxxx&am=4&autop=(value)&autof=(value)&vastURL=[original-VAST-URL]<br />
</syntaxhighlight><br />
<br />
<br />
The Nielsen Digital Ad Ratings system also features the ability to record Viewability information such as: How long an Ad has been visible on the screen, and what portion on the Ad. This is an additional feature that can be purchased from your Nielsen Client Services Representative.<br />
<br />
Viewability for display ads can ONLY be offered through the JavaScript tags.<br />
<br />
<blockquote>The above tags are just examples and should not be placed in any live site or ad server. You will be provided with tags specifically designed for your media plan/campaign or be able to download tags after creation in CMI (Campaign Management Interface)</blockquote><br />
<br />
== Standard DAR Tag ==<br />
The DAR tag is available as a 1x1 pixel. The following pixel/tag parameters must be specified for all DAR tags, 1x1, regardless of implementation type: browser, mobile browser, mobile app or connected device.<br />
<br />
{| class="wikitable" <br />
|-<br />
! Tag Parameter<br />
! Description<br />
|-<br />
| CI<br />
| Client ID: the ID that is associated with the DAR account that processed tag data is associated with. Will always be hardcoded to a Nielsen generated value that comes from the Nielsen campaign management system<br />
|- style="background-color:#eff8ef;"<br />
| AM<br />
| Ad Server: an ad server participating on the campaign media-plan. This is an internal Nielsen generated value when the ad server is indicated on the campaign during setup<br />
|-<br />
| CA<br />
| Campaign Id: this is the ID associated with your DAR campaign. Unless you are creating and managing the Nielsen campaign via the DAR Tag API, then this parameter value will always be generated from the Nielsen campaign management system. Note: often maps to a media-plan I/O Id<br />
|- style="background-color:#eff8ef;"<br />
| CR<br />
| Creative Id: DAR does not currently report at the creative level; can be hard coded ad server id or associated with a macro expansion<br />
|-<br />
| PC<br />
| Placement Id: can be generated by the ad server via macro expansion or generated by the Nielsen campaign management system. Note: often maps to one of Ad Unit Id, Line Item Id or Video Ad Id<br />
|- style="background-color:#eff8ef;"<br />
| CE<br />
| Site Id: the Id that identifies a publisher site that the placement needs to be mapped to. Maps into the Nielsen MarketView database. Note: can be hardcoded to a pre-registered ad server site id in the Nielsen system or a macro expansion where more than one pre-existing site ids have been made known to Nielsen<br />
|-<br />
| R<br />
| Cachebuster (web): timestamp / random number. Generated by ad server<br />
|- style="background-color:#eff8ef;"<br />
| AT<br />
| Fixed value: “view”<br />
|-<br />
| RT<br />
| Fixed value: “banner”<br />
|- style="background-color:#eff8ef;"<br />
| ST<br />
| Fixed value: “image”<br />
|}<br />
<blockquote> Do not URL encode the values</blockquote><br />
<br />
== Additional Parameters ==<br />
In this section we describe the additional parameters that the DAR tag can support, specifically Hashed Email, UID2 values, along with Page URL and Bundle Identifier if available. Please work with your Nielsen Technical Account Manager on deciding which of the following parameters to append to the standard DAR tag. <br />
<br />
'''Web Browser DAR tag (cookie based persons identification)'''<br />
<syntaxhighlight lang="html"><br />
https://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner<br />
&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=<siteid>&r=<timestamp><br />
</syntaxhighlight><br />
<br />
'''Web Browser PLUS tag'''<br />
<syntaxhighlight lang="html"><br />
https://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image<br />
&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=0000]&hem_sha256=<value>&uid2=<value>&uid_token=<value>&si=<value>c68=bndlid,com.tam.nielsen.com<br />
</syntaxhighlight><br />
<br />
=== HEM Support (Hashed Email) ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"| Hashed Email <br />
| User’s email address that has been run through a hashing algorithm (e.g. SHA256, MD5, SHA1)<br />
to create a unique string. If a client is unable to determine hashing type, they should pass using &hem_unknown parameter.<br />
|style="width: 20%"|<code>&hem_unknown</code></br><code>&hem_sha256</code></br><code>&hem_md5</code></br><code>&hem_sha1</code><br />
|}<br />
<br />
<blockquote>Please use the parameter that matches your hashing algorithm.<br> For example, if you are using sha256 to encode the email address, then use <code>hem_sha256={encrypted_value_here}</code><br />
</blockquote><br />
Example:<br />
<syntaxhighlight lang="javascript"><br />
hem_sha256=tMmiiTI7IaAcPpQPFQ65uMVCWH8av9jw4cwf/F5HVRQ=<br />
</syntaxhighlight><br />
<br />
=== Unified ID ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"| Unified ID 2.0<br />
| An identifier based on a user’s verifiable PII (e.g. hashed email). UID2.0 was initially created by The Trade Desk (TTD)</br> and is now managed by Prebid.<br />
| <code>&uid2</code><br />
|-<br />
| Unified ID 2.0 Token<br />
| Encrypted Unified ID 2.0<br />
| <code>&uid_token</code><br />
|}<br />
<br />
Example:<br />
<syntaxhighlight lang="javascript"><br />
uid2=MTKVpUAzwYAPnHrtfE0wlINOMzhU7UUEjjVdCdRu63k=<br />
uid_token=AgAAAAPFR0zA5ogv/yaAPiUsAdZPsfqS8QlDSGxAB+rr8yekFs3AjLYVk5qqqiyV2XHbSuwzHmxSlLeQeKQI1mp015jsNnpX5/xGgXldcgVz+gFnyh3T8/3agMwRmyrhCxG4oH2C7<br />
fc48AQk2eotE7FW0ZDEYM8fD9ZxDaxFUC/OV3OuZA&<br />
</syntaxhighlight><br />
<br />
=== Page and Bundle ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"|Page URL<br />
| style="width: 65%"| Canonical URL of the content where the Ad creative is served. (e.g. https://example.com/news/tech/article.html) The parameter value has to be encoded with JavaScript’s encodeURIComponent() method or equivalent. <br />Example: si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
| <code>&si</code><br />
|-<br />
| App Bundle ID<br />
| The app’s unique bundle ID (e.g. com.example.myapp). The ID can be used to look up the App in Apple’s App Store</br> or the Google Play Store. References:https://developer.android.com/studio/build/application-idhttps://developer.apple.com/documentation/appstoreconnectapi/bundle_ids<br />
| <code>&c68=bndlid,</code><br />
|}<br />
<br />
Example:<br />
<syntaxhighlight><br />
si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
c68=bndlid,com.tam.nielsen.com<br />
</syntaxhighlight><br />
<br />
== Supported Creative Types ==<br />
<br />
For consistency, Nielsen recommends tagging as much of the campaign creative types as possible, including site-served elements. '''Note:''' Nielsen may need to review/test on a case-by-case basis.<br />
<br />
Nielsen Digital Ad Ratings supports banner ads, rich media and video units that are capable of being tagged with a 3rd party tracking pixel.<br />
<blockquote>Some examples of non-standard campaign items that may be tagged include:<br />
* microsite pages<br />
* site “skins’”<br />
* online mini-games<br />
* streaming video<br />
* pre-roll video banners<br />
</blockquote><br />
Most often, these items will need to be site served and our pixel will need to be provided to the site to implement directly.<br />
<blockquote>The following are items not tagged:<br />
* click command/text links<br />
* default/backup ads in a 3rd party ad server<br />
* static ‘logo’ creatives<br />
</blockquote><br />
<br />
Digital Ad Ratings Viewability Solution: All standard ad units listed under [http://www.iab.net/displayguidelines Universal Ad Package (UAP)] on are supported for Viewability.<br />
<br />
Placements and sites that cannot support JavaScript cannot support Viewability.<br />
<br />
== How the Tag Works ==<br />
<br />
The following describes the masked javascript version of the tag. <br><br />
For the non-masked pixel version of the tag, steps 5-8 would be collapsed to just 2 steps.<br />
<br />
[[File:image3-dar.png|right|500px]]<br />
# End-user uses her web browser to visit a website that contains an ad creative being measured by Nielsen.<br />
# Website sends web page back to end-user. (Web page contains HTML describing web content & ads)<br />
# End-user’s web browser requests the ad creative from Ad Server<br />
# Ad Server sends an iframe ad creative back to the end-user which contains the Nielsen measurement tag<br />
# End-user’s web browser makes a request to the Nielsen servers.<br />
## The tag’s HTTP request contains a campaign ID and placement, which is collected by Nielsen<br />
## The Nielsen system checks the user’s machine for an opt-out cookie – if one exists the process ends here<br />
## The Nielsen system checks to see if the campaign value in the tag was selected for Viewability. If so it downloads the Integral Ad Science tag to the end-user’s browser.<br />
# Nielsen server sends JavaScript code back to end-user’s web browser, including a 1x1 pixel.<br />
# End-user’s web browser executes JavaScript code and makes an iframe request to Nielsen server to enable the “referrer masking redirect”<br />
# Nielsen server sends an HTML message to the end-user’s web browser.<br />
# End-user’s web browser executes HTML and requests a 1x1 pixel from the Data Provider using Nielsen server information as the HTTP referrer – thus masking the Website’s information<br />
## The campaign ID and placement ID are passed through to Data Provider in an encrypted format<br />
# If Viewability is enabled the JavaScript will download a Javascript tag that calls the viewability vendor (either Nielsen or 3rd Party) to begin tracking inview metrics.<br />
# Data Provider responds with a 1x1 pixel. End process.<br />
<br />
== Share Your Delivered Impressions ==<br />
<br />
'''Why the Media Plan is Needed'''<br />
<br />
Knowing the delivered impressions also helps Nielsen run automated QA checks, for example triggering alerts when data does not appear for a placement on an expected date. This ensures overall quality, and reduces errors in the tagging process.<br />
<br />
It is the responsibility of the client to send Nielsen an impression delivery report, generally known as the “ad server report.” Nielsen can provide the client with a template with the inputs required to complete the quality checks. If the client does not send these reports, Nielsen will not be able to complete the quality checks. Below are instructions on how to send these reports to Nielsen.<br />
<br />
'''How to Share Your Delivered impressions'''<br />
<br />
Set up an automated daily report from your ad server containing Site Name, Site ID, Placement Name, Placement ID, and data date.<br />
<br />
A secondary method to share your media plan information is to grant Nielsen “Reporting access” to your campaign in the designated ad server (such as DCM). To do this, simply grant the login [http://mailto:clientreporting@nielsen.com clientreporting@nielsen.com] access. In doing so Nielsen can directly access your media plan information, which enables us to check for updates, and reconcile any<br /><br />
discrepancies.<br />
<br />
<blockquote>Please note that Nielsen is currently in discussions with several leading Ad Servers regarding direct integration between Nielsen and the ad server platforms. Once completed this could someday enable Nielsen to retrieve Media Plans on a completed automated basis.<br />
</blockquote><br />
<br />
== Apply the Tag ==<br />
=== Tag Generation===<br />
<br />
Your Nielsen representative will walk you through the Campaign Management Interface so that you can download tags at will at any point in the campaign.<br />
<br />
Nielsen supports macro-based tag generation for several major ad servers. Nielsen’s Technical Account Manager (TAM) can assist you in leveraging macro-based tags.<br />
<br />
=== Tag Application ===<br />
<br />
Apply the tag according to the 3rd party tracking pixel specifications of your ad server. If additional guidance is needed, please consult with the Technical Account Manager (TAM) for more specific instructions or recommendations, if available.<br />
<br />
'''Special Note: DAR Pixel Tags for Video'''<br />
Nielsen’s recommended “Best Practice” for tagging your video ads is to apply the Digital Ad Ratings tag as close to the beginning of the video as possible and after initiation of the ad stream, when the ad itself begins to appear on the user’s browser, closest to the opportunity to see. To ensure video content initiates during Digital Ad Ratings measurement, tags should always be placed post buffer. Recognizing that it’s not always possible to give the Nielsen pixel priority positioning, please be aware that the placement of the tag should be discussed with the publisher/advertiser counterparty so that both sides agree on the measurement approach.<br />
<br />
'''Special Note: Video Auto-Play and Auto-Refresh'''<br />
In accordance with MRC requirements, Clients must append “autop” parameter to detect click to play vs auto-play to their video tags. To detect auto-refresh (page refresh), “autof” parameter must be included (not limited to video tags).<br />
<br />
<syntaxhighlight lang=javascript><br />
<img src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3&ca=cmpXXXX&cr=&pc=plcXXXX&<br />
autop=(value)&autof=(value)&r=[timestamp]" width="1" height="1" alt="" /><br />
</syntaxhighlight><br />
<br />
==== autop ====<br />
- A value of 1 will be passed when Auto-Play is detected. (e.g. autop=1)<br /><br />
- A value of 2 will be passed when Click-to-Play is detected. (e.g. autop=2)<br /><br />
- When no value or parameter is not present, impressions are labeled as Unknown Play.<br />
<br />
==== autof ====<br />
- A value of 1 will be passed when Auto-Refresh is detected. (e.g. autor=1)<br /><br />
- When no value or parameter is not present, impressions are labeled as Unknown Refresh.<br />
<br />
'''Special Note for Video Viewability Implementation:'''<br />
* Nielsen does not support any Flash based video players for viewability measurement.<br />
* The ad and tag must be in the same division (div tag) in order to track Viewability<br />
* Video:<br />
** VPAID compliant players<br />
** HTML5 Players (Flash not supported)<br />
** VPAID or mp4 creative<br />
** Video player must support VPAID and mp4<br />
<br />
=== Workflow and Tag Requirements for Nielsen Viewability with Qualified Ad Audience ===<br />
The following steps represent the tag/data flow between the publisher and Nielsen, through to final reporting.<br />
<blockquote> Please note that the assigned values for <code>CA, CI, AM, AM, PC and CR </code> in the example tags below are for illustrative purposes only to demonstrate the VW viewability state tag token. These values will need to be replaced with client specific data and/or macros specific to the ad serving situation.</blockquote><br />
<br />
# Ad creative exposed to the user<br /><br />
# Ad Server technology fires DAR tag on the publisher site<br /><br />
# Viewable state detected by Nielsen technology on publisher property; tag/signal sent to Nielsen collection system<br /><br />
# Nielsen collection system generates and executes the DAR tag with one of the following viewable states.<br />
# DAR data processing and reporting aggregates viewable impression states by campaign, placement and demographic attribution.<br />
<br />
==== Viewability Base URL &amp; Ping Paths ====<br />
<code> events.imrworldwide.com/VALUE?... </code><br />
<br />
==== JavaScript Ping Path Values ====<br />
<br />
'''Display Tag:'''<br />
* /cgi-bin/m - DAR Main Ping<br />
* /imp - Impression Ping<br />
* /nmp - Measure Ping<br />
* /psp - Primary Standard Ping<br />
* /1sp - 1 Second Ping<br />
* /5sp - 5 Second Ping<br />
* /15sp - 15 Second Ping<br />
* /120sp - 120 Second Ping<br />
* /fp - Final Ping<br />
* /er - Error Ping<br />
<br />
<br />
'''Video Tag'''<br />
* /cgi-bin/m - DAR Main Ping<br />
* /imp - Impression Ping<br />
* /nmp - Measure Ping<br />
* /psp - Primary Standard Ping<br />
* /qp - Quarterly Ping (25%/50%/75%/100%)<br />
* /fp - Final Ping<br />
* /er - Error Ping<br />
<br />
==== Nielsen DAR Tag/VPAID Query Strings ====<br />
<br />
'''Measure Ping'''<br />
<syntaxhighlight lang=html><br />
/nmp?impid=VALUE&ca=VALUE&cr=VALUE&pc=VALUE&ci=VALUE&am=VALUE&ce=VALUE&cy=VALUE&at=view&st=image&mr=1&ty=js&rt=banner&meas=VALUE&rend=VALUE&ss=VALUE&vp=VALUE&as=VALUE&al=VALUE&diag=VALUE<br />
</syntaxhighlight><br />
<br />
'''Primary Standard Ping'''<br />
<syntaxhighlight lang=html><br />
/psp?impid=VALUE&vs=VALUE<br />
</syntaxhighlight><br />
<br />
'''Quarterly Ping (25%)'''<br />
<syntaxhighlight lang=html><br />
/qp?impid=VALUE&qpc=25&src=njs&diag=VALUE<br />
</syntaxhighlight><br />
<br />
'''Finish Ping'''<br />
<syntaxhighlight lang=html><br />
/fp?impid=VALUE&vs=VALUE&ss=VALUE&vp=VALUE&as=VALUE&al=VALUE&vts=VALUE=&ats=VALUE==&diag=VALUE<br />
</syntaxhighlight><br />
<br />
'''Error Ping'''<br />
<syntaxhighlight lang=html><br />
/er?impid=VALUE&amp;ca=VALUE&amp;ci=VALUE&amp;cr=VALUE&amp;ce=VALUE&amp;pc=VALUE&amp;am=VALUE&amp;ercd=VALUE<br />
</syntaxhighlight><br />
<br />
=== Workflow and Pixel Tag Requirements for 3rd Party Viewability ===<br />
The following steps represent the tag/data flow between publisher, Nielsen and the 3rd party viewability vendor (hereafter referred to as “vendor”), through to final reporting.<br />
<br />
<blockquote>Please note that the assigned values for CA, CI, AM, AM, PC and CR in the example tags below are for illustrative purposes only to demonstrate the VW viewability state tag token. These values will need to be replaced with client specific data and/or macros specific to the ad serving situation.</blockquote><br />
<br />
'''Requirements'''<br />
* Ad creative exposed to the user<br /><br />
* Vendor technology fires DAR tag on the publisher site<br />
<syntaxhighlight lang=html><br />
//secure-gl.imrworldwide.com/cgi-bin/m?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignId]&amp;cr=[creativeId/macro]<br />
&amp;pc=[placementId/macro]&amp;r=[timestamp]<br />
</syntaxhighlight><br />
* Viewable state detected by vendor detection technology (i.e. vendor Javascript containertag) on publisher property; tag/signal sent to vendor collection system<br />
* Vendor collection system generates and executes the DAR tag with one of the following viewable state (see highlight) embedded<br />
<br />
==== onMeasureable ====<br />
<syntaxhighlight lang=html><br />
//secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignI d]&amp;cr=[creativeId/macro]&amp;pc=<br />
[amvalue]_[placementId/macro]&amp;vw=meas&amp;r=[timestamp]</syntaxhighlight><br />
<br />
==== onInViewMRC ====<br />
<syntaxhighlight lang=html><br />
//secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignId]&amp;cr=[creativeId/macro]<br />
&amp;pc=[amvalue]_[placementId/macro]&amp;vw=view&amp;r=[timestamp ]</syntaxhighlight><br />
==== onSuspicious====<br />
<syntaxhighlight lang=html><br />
//secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignI d]&amp;cr=[creativeId/macro]<br />
&amp;pc=[amvalue]_[placementId/macro]&amp;vw=susp&amp;r=[timestamp ]</syntaxhighlight><br />
<br />
* DAR data processing and reporting aggregates viewable impression states by campaign, placement and demographic attribution.<br />
<blockquote>'''Special Note for Nielsen Viewability with Qualified Ad Audience:''' Primary owner of campaign must provide assigned Technical Account Manager (TAM) VPAID tags per site/placement in order for VAST Wrapper to be delivered back to primary owner for implementation within their respective ad server, CMS, video serving platform, etc.<br />
</blockquote><br />
<br />
<blockquote>'''Special Note for Server Side Dynamic Ad Insertion:''' In cases where Server Side Dynamic Ad Insertion (SSDAI) is present, the Nielsen tag cannot execute unless the client side video player is coded to fire impression pixels when ads play. When this happens, all of the existing specifications for tag format, time, and criteria of execution (i.e. on play of ad) previously documented must be followed.<br />
</blockquote><br />
<br />
== QA Testing the Tag ==<br />
<br />
Nielsen’s Technical Account Manager (TAM) will coordinate a plan to test fire tags in advance of the campaign go-live date.<br />
<br />
In order to test the implementation of the Nielsen tag, at least one or two (more are<br /><br />
recommended) live URLs should be provided to the TAM. If a live page cannot be made available, at staging page or offline test page should be provided. The object of this is so that the TAM can see the Nielsen call being made live, exactly as it has been implemented, to verify all of the values expected – dynamic and static - are in the tag. A spot check of a couple of placements should be sufficient unless otherwise requested. In lieu of an actual test page, we may recommend you provide a screenshot of you testing the implementation from your end, showing the Nielsen call exactly as it is being called.<br />
<br />
Additionally, we will verify that the tags delivered have begun to receive data once the campaign actually goes live and will regularly (every 7-14 days, minimally) compare the Nielsen reporting to your 3rd party or publisher reporting to ensure we are capturing all of the data for all of the placements, as expected, and that the overall gap between your reporting and the Nielsen reporting is kept to a minimum.<br />
<br />
'''Detailed steps for confirming proper tag implementation'''<br />
* Open Chrome browser and enable “Developer Tools” (shortcuts: PC, “F12” - Mac, “Command+Option+I”)<br />
<blockquote>'''NOTE''' - Other browsers or debugging tools can also be used as an alternative (ie Firefox w/HttpFox extension, Fiddler, Charles, Wireshark, etc).</blockquote><br />
* Paste test page into browser URL field<br />
* Toggle to the “Network” tab<br />
** To isolate the DAR ping you can also input “imr” into the filter box<br />
[[File:image4-dar.png|900px]]<br />
<br />
<blockquote>'''TIP''' - If DAR tag does not display try refreshing the test page</blockquote><br />
=== If IMAGE tags were used ===<br />
'''Confirm call status is 302'''<br />
This ensures a redirect has been made to our Data Enrichment Provider<br />
[[File:image5-dar.png|600px]]<br />
<br />
'''Clicking on the call and navigating to the “Headers” tab will allow you to better evaluate tag construction'''<br />
[[File:image6-dar.png|500px]]<br />
<br />
'''The “Query String” section will disclose the tag parameter'''<br />
Confirm these values are displaying as expected<br />
<blockquote>'''NOTE''' - If ad server macro tokens are used, please ensure they are expanding properly<br />
</blockquote><br />
[[File:image7-dar.png|600px]]<br />
<br />
'''Optional - Review Data Enrichment Provider call'''<br />
his can be identified by searching for “brandlift”<br />
[[File:image8-dar.png|594px]]<br />
Call status should be 200<br />
<br />
<blockquote>'''NOTE''' - campaign tag parameters are encrypted when passed to Data Enrichment Provider</blockquote><br />
[[File:image9-dar.png|600px]]<br />
<br />
=== If JavaScript tags were used ===<br />
<br />
Steps are same as the above except for the following:<br />
* Two Nielsen (“imr”) calls will be made, both with status of 200<br />
** 1st - logs the impression on Nielsen servers<br />
** 2nd - initiates the call to our Data Enrichment Provider<br />
[[File:image10-dar.png|592px]]<br />
* 3rd (Optional) call is the same as above, review Data Enrichment Provider ping. This can be identified by searching for “brandlift”<br />
[[File:image11-dar.png|580px]]<br />
<br />
== Managing Campaign Updates ==<br />
<br />
As part of the campaign monitoring process, your Nielsen TAM will stay in close contact with you throughout the campaign, including scheduling periodic check-ins to check on the campaigns (approximately every 7-14 days, but could be more often, as needed). If you have provided reporting access to the campaign via your 3rd party or have scheduled a report to be delivered on a regular (weekly) basis, this can significantly expedite the monitoring of your campaign.<br />
<br />
If you have any questions regarding setting up the reporting to be delivered, fields that will need to be included, etc., please reach out to the TAM assigned to your campaign. If not providing direct access to reporting, please schedule reporting to be delivered on a weekly basis.<br />
</blockquote><br />
<br />
== Frequently Asked Questions ==<br />
<br />
'''What is a tag?'''<br />
<br />
For our purposes, a tag is an HTML code that is placed directly on a website or inside a 3rd party ad server to track exposure to an online advertisement. Adding the Nielsen tag to the<br /><br />
banners/videos/etc. is referred to in general as ‘tagging a campaign’.<br />
<br />
'''What is served by the Nielsen tag?'''<br />
<br />
The tag call is a simple 1x1 pixel image call. There is not a survey delivered at the time of ad call so this is not intrusive to the end user and should not adversely affect site page load times. <br />
<br />
'''What should be tagged?'''<br />
<br />
As much of the campaign that can be tagged, should be, for consistency. In most cases, we generally do not tag items such as: click command/text links, default/backup ads in a 3rd party ad server, or static ‘logo’ creatives. Whenever possible, we will request that you attempt to tag all other creative types, including site-served elements.<br />
<br />
'''Is there a way to differentiate between video “auto-play” and “click-to-play” impressions?'''<br />
<br />
The Nielsen pixel does not gather this type of granularity if the events are both sharing the same ad server placement ID. If it is desirable to compare the performance between these two events, our recommendation is to traffic these as individual placements within your ad serving<br /><br />
technology.<br />
<br />
'''What is the best way to add the Nielsen tag to my campaign?'''<br />
<br />
The Nielsen pixel should be called as close to the same time as the banner ad/creative element on which you would like to track exposure. Typically, this is handled by placing our tag inside a 3rd party ad server, such as Google’s DCM or a Rich Media vendor, such as PointRoll. However, if need be, our tag can be placed directly on a site page, immediately after the ad call in the same &lt;/div&gt; as the creative file. Further instruction can be provided on the kickoff call or we can work directly with trafficking contact(s) to get the tags in place.<br />
<br />
'''Do we need to use a 3rd party ad server to use the Nielsen tag?'''<br />
<br />
The short answer is no. In a lot of cases, we have provided a tag that can be implemented directly on a site. The benefit of placing our tag inside a 3rd party ad server is that we can provide a single tag (or minimal number of tags) that contain macros to simplify the tagging process.<br />
<br />
'''Is there anything that can’t be tagged?'''<br />
<br />
We may need to review/test on a case-by-case basis, but realistically most campaign elements can be tagged. Most often, these items will need to be site served and our pixel will need to be provided to the site to implement directly. Some examples of non-standard campaign items that have been tagged before include: microsite pages, site ‘skins’, online mini-games, streaming video, pre-roll video banners.<br />
<br />
'''The site has told us that they can accept only one pixel for the site served element. Can we append your tag to the end of ours?'''<br />
<br />
If you are serving a DCM 1x1 pixel to track these elements of your campaign, we have a method for placing our tag behind this call, to be served as a redirect. For other situations, we may need to discuss further and consider other options.<br />
<br />
'''I’m using more than one Nielsen study/product on this campaign. Will I need multiple/different tags for each?'''<br />
<br />
You should not need separate tags for each study. To keep the tagging process simple, we have designed our products so that a single tag can be used for multiple online studies, however, your TAM needs to be informed of all studies before launch so that they can be enabled.<br />
<br />
'''How much detail can be tracked with the Nielsen tag?'''<br />
<br />
Typically, we do an overall read for these studies, but we can segment the data by site, placement, ad size or creative, for example. If more granular data is desired, this should be discussed ahead of the campaign launch and planned for at the time of tag creation. ''We cannot segment the data if we have not tagged for it'' -- multiple tags will need to be created and implemented properly. Note that this can often be a time consuming process for the client trafficker and additional time should be allotted if this is needed. Lastly, keep in mind that exposure sample size may be a factor for segmenting the data at a more granular level.<br />
<br />
'''Why is it recommended to implement a timestamp or random number on the tag?''' This value will ensure that the tag call will not be cached on a user’s browser. It’s not absolutely necessary to implement for the tag to work, but without it you may see a larger gap between the impressions ran and what Nielsen captures. It is recommended to minimize this gap.<br />
<br />
'''For campaigns involving Facebook, what can’t be tagged on their site?'''<br />
<br />
Fan/Like pages are not allowed to be tagged, per Facebook. Additionally, Marketplace slots are not allowed to be tagged as these are user generated ads.<br />
<br />
'''What if it is not possible to provide a test or staging page before launch?'''<br />
<br />
While not ideal, we can view raw impression numbers on the day of the launch as well as review a live example if a URL is provided. Another option would to test from the client/site side and provide a screenshot of the Nielsen call being made using a proxy tool (HTTPWatch, Fiddler, Charles, etc.) – prior to launch. The aim either way is to minimize missing impressions for your campaign, so it is in your best interest to provide for this testing if you can.<br />
<br />
'''What is considered to be an acceptable gap in reporting?'''<br />
<br />
In a perfect world, we’d like to see no gap in the numbers. We realize this is simply not possible – it is a factor of the Internet and having different counting methodologies, so we will aim for the lowest overall gap we can. Even with everything trafficked correctly; it is not uncommon to see gaps in the range of 5 to 10%, so we shoot for this range (if it’s lower than that, that’s great). If it’s greater than 10%, it usually indicates that there was something that was missed from being tagged or there’s an additional issue that requires further attention. When issues arise, we make all attempts to highlight and communicate the issue seen, to minimize the overall impact to the study, but are reliant on the client to ensure the issue is fixed. In a campaign where there are issues such as this, we try to keep the gap under 20% and will document any issues found. What are the capabilities for tagging video and video based ads?<br />
<br />
Our tag is not a specific limitation as it is one of the simplest things that can be served – a 1x1 image. That being said, much of the video implementation limitations are often dictated by the video vendors themselves. Where you can add our tag is dependent on the capabilities of these vendors. Some have the ability to place the tag in multiple locations in the video (i.e. beginning, middle, end – multiple tags will be needed to separate these out) and some simply place the pixel directly on the webpage, next to video being served. Further discussion may need to happen with the vendor, Nielsen and the client to determine the optimum implementation that meets the client's needs.<br />
</blockquote></div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Denmark_Video_Cloud_API&diff=5693DCR Denmark Video Cloud API2022-03-14T19:55:29Z<p>LaMarHolmes: /* Interruption Scenarios */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International DCR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
= DCR Integration Utilizing Cloud API =<br />
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.<br />
__TOC__<br />
==Prerequisites==<br />
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.<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 15%;" | Item<br />
! Description<br />
! Source<br />
|-style="background-color:#d0f6f8;"<br />
|| '''App ID (appid)''' || Unique ID assigned to the player/site and configured by product. || Provided by Nielsen<br />
|}<br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTP GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID. <br />
** '''Note: P prefix must be removed before adding it to the URL'''<br />
** Example App ID with P prefix: "PDF20695-XXXX-XXXX-XXXX-3E334133D917"<br />
** <code>https://sc-eucert.nmrodam.com/nmapi/v2/DF20695-XXXX-XXXX-XXXX-3E334133D917/[sessionID]/a?b=[payload]</code><br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sc-eucert.nmrodam.com/nmapi/v2/</code><br />
*Production: <code>https://capi-dmk.nmrodam.com/nmapi/v2/</code><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sc-eucert.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [Unix time in ms],<br />
"sessid": [unique view session ID for each video play]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID and send EMM Ping===<br />
<br />
====Create Session ID====<br />
<br />
A unique Session ID <code>[sessionID]</code> must be created upon app launch and provided in the URL. This will allow the measurement to occur for the entire duration that a user is within the app.<br />
<br />
A Session ID needs to be completely unique so it is recommended to use our generation method example provided below to create unique alpha-numerical 29 characters + 10 characters UTC timestamp, 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.<br />
<br />
Session ID example: '''LsTYTmZQPwdchsNZkdtJp9lErjgAp1632729088'''<br />
<br><br />
<br />
<syntaxhighlight lang="javascript"><br />
'''// Create random GUID'''<br />
function buildGUID() {<br />
var UAIDbase62Characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";<br />
var UAIDpayloadLength = 29;<br />
<br />
function UAIDgetRandom62() {<br />
var r1;<br />
do {<br />
r1 = Math.floor(Math.random() * (16 * 62));<br />
} while (r1 > 61); <br />
return r1;<br />
}<br />
<br />
var uid = '';<br />
for (var a = 0; a < UAIDpayloadLength; a++) {<br />
uid += UAIDbase62Characters.charAt(UAIDgetRandom62());<br />
}<br />
uid += Math.floor(new Date().getTime() / 1000);<br />
return uid;<br />
}<br />
</syntaxhighlight><br />
<br><br />
<br />
Upon exiting the app, the session will need to be terminated using the delete event. <br><br />
Sessions will automatically expire after 30 minutes of cloud inactivity.<br />
<br />
====Send EMM Ping====<br />
An EMM Ping must be sent using the created unique Session ID <code>[sessionID]</code> upon start of the first stream playback.<br />
<syntaxhighlight lang="javascript"><br />
https://[sessionID].uaid.nmrodam.com/<br />
</syntaxhighlight><br />
Also see [[#Review the Reference Implementation for VoD and Live Streams|Reference Implementation for VoD and Live Streams]] for your reference.<br />
<br />
===Create First Party ID===<br />
* 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.<br />
The default expiration date should be set to the equivalent of 180 days. <br />
* 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.<br />
<br />
===Create View Session ID for each Video Start===<br />
An View Session ID <code>[sessid]</code> must be created upon start of each stream playback, sessid is unique per video play.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sc-eucert.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"fpid": "First Party ID",<br />
"fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", //ad load flag<br />
"subbrand": "c05", // channel ID or subrand provided by Nielsen<br />
"stationId": "TESTXXYYSSWWLL",<br />
"islivestn": "y",<br />
"pbstarttm": "1631098029"<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000", //unix timestamp in milliseconds <br />
"sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play<br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || ✓<br />
|-<br />
| apn || app name || custom || ✓<br />
|-<br />
| apv || app build version || custom || ✓<br />
|-style="background-color:#d0f6f8;"<br />
| fpid || First Party ID || custom || ✓<br />
|-style="background-color:#d0f6f8;"<br />
| fpcrtm || Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds) || custom || ✓<br />
|-<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"fpid": "First Party ID",<br />
"fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
<br/><br />
<blockquote> program and title metadata values should be passed to SDK as UTF-8 strings. </blockquote><br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || "content" for main content || ✓<br />
|-<br />
| assetid || unique ID assigned to asset || custom<br>(no [[Special Characters]]) || ✓<br />
|-<br />
| program || name of program || custom || ✓<br />
|-<br />
| title || episode name || custom || ✓<br />
|-<br />
| 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)|| ✓<br />
|-<br />
| 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") || ✓<br />
|-<br />
| isfullepisode || full episode flag || <br />
* "y" full episode (full content for a program)<br />
* "n" non full episode (only one part of the entire content for a program , i.e. preview, sub-episodes)<br />
||<br />
✓<br />
|-<br />
|adloadtype || type of Ad load<br />
||<br />
:<br />
* "1" Linear - matches TV ad load <br />
* "2" Dynamic - Dynamic Ad Insertion (DAI)<br />
||<br />
✓<br />
|-style="background-color:#d0f6f8;"<br />
|stationId || Unique Gracenote Station ID generated by Nielsen that uniquely identifies a live channel<br />
||<br />
provided by Nielsen<br />
||<br />
✓<br />
|-style="background-color:#d0f6f8;"<br />
|islivestn || Indicates if a stream is playing on a live channel<br />
||<br />
:<br />
* "y" playing on a live channel<br />
* "n" otherwise i.e. VoD<br />
||<br />
✓<br />
|-style="background-color:#d0f6f8;"<br />
|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)<br />
||<br />
i.e. "1631098029" for live stream and ""(empty string) for a VoD.<br />
||<br />
✓<br />
|-<br />
| 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) <br />
||<br />
provided by Nielsen <br />
||<br />
✓ <br />
|}<br />
<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "unique_content_id",<br />
"program": "program name",<br />
"title": "episode title",<br />
"length": "length in seconds",<br />
"airdate": "20200713 10:22:00",<br />
"isfullepisode": "y",<br />
"adloadtype": "2",<br />
"subbrand": "c05",<br />
"stationId": "TESTXXYYSSWWLL",<br />
"islivestn": "y",<br />
"pbstarttm": "1631098029"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata (optional for DR) =====<br />
The Ad Metadata (if applicable) should be passed for each individual ad.<br />
<br />
Note: All metadata values should be passed as UTF-8 strings.<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of Ad || <code>"preroll"</code>, <code>"midroll"</code>, <code>"postroll"</code> <br> <code>"ad"</code> - If specific type can not be identified.|| ✓<br />
|-<br />
| assetid || unique ID assigned to Ad || custom<br>(no [[Special Characters]]) || ✓<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "unique_preroll_ad_id"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <code>"playhead"</code> || <br />
<br />
===== Handling Playhead =====<br />
<br />
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.<br />
<br />
'''General'''<br />
* Playhead position in seconds, must be passed as a whole number every 10 seconds. <br />
* The final playhead position should be sent before before sending "complete" event when content playback is complete. <br />
<br />
'''Live Stream'''<br />
* 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.<br />
<br />
'''VoD Stream'''<br />
* 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, ....<br />
<br />
'''End of an Asset'''<br />
* Final postion must be sent at the end of Content or Ad playback<br />
<br />
'''Ads'''<br />
* The final playhead position must be sent when switching from content to ad, or ad to content.<br />
* For Ad Pods, playhead must be called for each individual ad.<br />
* When content has resumed following a mid-roll ad break, the next playhead position must continue where the previous content segment left off.<br />
<br />
'''User Actions'''<br />
* 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.<br />
* PAUSE: When content is paused, send current playhead position and stop passing playhead position until content is resumed.<br />
* EXIT Stream: If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
|-<br />
| <code>"complete"</code> || The complete event must be sent when full playback of the content has completed . 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.<br />
|-<br />
| <code>"delete"</code> || The delete event is 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || ✓<br />
|-<br />
| <code>"position"</code> || playhead position in seconds or Unix time in seconds || <code>"300"</code> || ✓<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || ✓<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || ✓<br />
|-style="background-color:#d0f6f8;"<br />
| <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> || ✓<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000", //unix timestamp in milliseconds<br />
"sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle for VoD Stream =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle for VoD Stream - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
'''Note:''' A session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = LsTYTmZQPwdchsNZkdtJp9lErjgAp1632729088 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sc-eucert.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"fpid": "U4EDwDcpvWIbguYVyjlhzS1v0eaov1631180980",<br />
"fpcrtm": "1631098029000"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2" // ad load flag,<br />
"subbrand": "c05",<br />
"stationId": "TESTXXYYSSWWLL",<br />
"islivestn": "y",<br />
"pbstarttm": "1631098029",<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000", //unix timestamp in milliseconds <br />
"sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609" // unique for each video play<br />
}<br />
<br />
// Append payload to URL<br />
function sendPayloadToNielsen() {<br />
var payloadStr = JSON.stringify(payload); // payload as string<br />
var imgPing = new Image();<br />
imgPing.onload = function() {<br />
// onload event, payload succesfull sent<br />
};<br />
imgPing.onerror = function() {<br />
// handle error i.e. wait and send again<br />
};<br />
imgPing.src = sessionURL+encodeURIComponent(payloadStr);<br />
}<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTP Response Code ====<br />
<br />
Confirm request was completed by viewing HTTP response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTP Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Review the Reference Implementation for VoD and Live Streams ==<br />
<br />
The Reference Implementation covers vod and Live use cases. <br />
It also covers DAI (Dynamic Ad Insertion) with preroll and postroll Ads.<br />
<br />
In order to start live stream select the checkbox "isLive" in the <code>Playback Settings</code> below the video player.<br />
<br />
Start the Reference Implementation for DK [https://nielsenonlinesupport.com/dk/cloudapi/index.htm?debug=true RefImplCloudAPIDK].<br />
<blockquote><br />
Review the Nielsen CloudAPI Call Sequence below the Video Player.<br />
</blockquote><br />
<br />
== Disclose Nielsen Privacy Statement ==<br />
<br />
In order to disclose Nielsen measurement privacy statement, please include the following items in your privacy policy:<br />
* A notice that the player includes third party measurement software that allows users to contribute to market research.<br />
* A link to the Nielsen Digital Measurement Privacy Policy located at https://sites.nielsen.com/priv/browser/dk/da/DigitalMeasurement.html .<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*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.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit, if the platform has the necessary exit callback events.<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTP Response ====<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sc-eucert.nmrodam.com/nmapi/v2/</code><br />
*Production: <code>https://capi-dmk.nmrodam.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://capi-dmk.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Denmark_Video_Cloud_API&diff=5692DCR Denmark Video Cloud API2022-03-14T19:54:39Z<p>LaMarHolmes: /* Event Types */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International DCR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
= DCR Integration Utilizing Cloud API =<br />
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.<br />
__TOC__<br />
==Prerequisites==<br />
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.<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 15%;" | Item<br />
! Description<br />
! Source<br />
|-style="background-color:#d0f6f8;"<br />
|| '''App ID (appid)''' || Unique ID assigned to the player/site and configured by product. || Provided by Nielsen<br />
|}<br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTP GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID. <br />
** '''Note: P prefix must be removed before adding it to the URL'''<br />
** Example App ID with P prefix: "PDF20695-XXXX-XXXX-XXXX-3E334133D917"<br />
** <code>https://sc-eucert.nmrodam.com/nmapi/v2/DF20695-XXXX-XXXX-XXXX-3E334133D917/[sessionID]/a?b=[payload]</code><br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sc-eucert.nmrodam.com/nmapi/v2/</code><br />
*Production: <code>https://capi-dmk.nmrodam.com/nmapi/v2/</code><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sc-eucert.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [Unix time in ms],<br />
"sessid": [unique view session ID for each video play]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID and send EMM Ping===<br />
<br />
====Create Session ID====<br />
<br />
A unique Session ID <code>[sessionID]</code> must be created upon app launch and provided in the URL. This will allow the measurement to occur for the entire duration that a user is within the app.<br />
<br />
A Session ID needs to be completely unique so it is recommended to use our generation method example provided below to create unique alpha-numerical 29 characters + 10 characters UTC timestamp, 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.<br />
<br />
Session ID example: '''LsTYTmZQPwdchsNZkdtJp9lErjgAp1632729088'''<br />
<br><br />
<br />
<syntaxhighlight lang="javascript"><br />
'''// Create random GUID'''<br />
function buildGUID() {<br />
var UAIDbase62Characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";<br />
var UAIDpayloadLength = 29;<br />
<br />
function UAIDgetRandom62() {<br />
var r1;<br />
do {<br />
r1 = Math.floor(Math.random() * (16 * 62));<br />
} while (r1 > 61); <br />
return r1;<br />
}<br />
<br />
var uid = '';<br />
for (var a = 0; a < UAIDpayloadLength; a++) {<br />
uid += UAIDbase62Characters.charAt(UAIDgetRandom62());<br />
}<br />
uid += Math.floor(new Date().getTime() / 1000);<br />
return uid;<br />
}<br />
</syntaxhighlight><br />
<br><br />
<br />
Upon exiting the app, the session will need to be terminated using the delete event. <br><br />
Sessions will automatically expire after 30 minutes of cloud inactivity.<br />
<br />
====Send EMM Ping====<br />
An EMM Ping must be sent using the created unique Session ID <code>[sessionID]</code> upon start of the first stream playback.<br />
<syntaxhighlight lang="javascript"><br />
https://[sessionID].uaid.nmrodam.com/<br />
</syntaxhighlight><br />
Also see [[#Review the Reference Implementation for VoD and Live Streams|Reference Implementation for VoD and Live Streams]] for your reference.<br />
<br />
===Create First Party ID===<br />
* 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.<br />
The default expiration date should be set to the equivalent of 180 days. <br />
* 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.<br />
<br />
===Create View Session ID for each Video Start===<br />
An View Session ID <code>[sessid]</code> must be created upon start of each stream playback, sessid is unique per video play.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sc-eucert.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"fpid": "First Party ID",<br />
"fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", //ad load flag<br />
"subbrand": "c05", // channel ID or subrand provided by Nielsen<br />
"stationId": "TESTXXYYSSWWLL",<br />
"islivestn": "y",<br />
"pbstarttm": "1631098029"<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000", //unix timestamp in milliseconds <br />
"sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play<br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || ✓<br />
|-<br />
| apn || app name || custom || ✓<br />
|-<br />
| apv || app build version || custom || ✓<br />
|-style="background-color:#d0f6f8;"<br />
| fpid || First Party ID || custom || ✓<br />
|-style="background-color:#d0f6f8;"<br />
| fpcrtm || Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds) || custom || ✓<br />
|-<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"fpid": "First Party ID",<br />
"fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
<br/><br />
<blockquote> program and title metadata values should be passed to SDK as UTF-8 strings. </blockquote><br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || "content" for main content || ✓<br />
|-<br />
| assetid || unique ID assigned to asset || custom<br>(no [[Special Characters]]) || ✓<br />
|-<br />
| program || name of program || custom || ✓<br />
|-<br />
| title || episode name || custom || ✓<br />
|-<br />
| 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)|| ✓<br />
|-<br />
| 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") || ✓<br />
|-<br />
| isfullepisode || full episode flag || <br />
* "y" full episode (full content for a program)<br />
* "n" non full episode (only one part of the entire content for a program , i.e. preview, sub-episodes)<br />
||<br />
✓<br />
|-<br />
|adloadtype || type of Ad load<br />
||<br />
:<br />
* "1" Linear - matches TV ad load <br />
* "2" Dynamic - Dynamic Ad Insertion (DAI)<br />
||<br />
✓<br />
|-style="background-color:#d0f6f8;"<br />
|stationId || Unique Gracenote Station ID generated by Nielsen that uniquely identifies a live channel<br />
||<br />
provided by Nielsen<br />
||<br />
✓<br />
|-style="background-color:#d0f6f8;"<br />
|islivestn || Indicates if a stream is playing on a live channel<br />
||<br />
:<br />
* "y" playing on a live channel<br />
* "n" otherwise i.e. VoD<br />
||<br />
✓<br />
|-style="background-color:#d0f6f8;"<br />
|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)<br />
||<br />
i.e. "1631098029" for live stream and ""(empty string) for a VoD.<br />
||<br />
✓<br />
|-<br />
| 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) <br />
||<br />
provided by Nielsen <br />
||<br />
✓ <br />
|}<br />
<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "unique_content_id",<br />
"program": "program name",<br />
"title": "episode title",<br />
"length": "length in seconds",<br />
"airdate": "20200713 10:22:00",<br />
"isfullepisode": "y",<br />
"adloadtype": "2",<br />
"subbrand": "c05",<br />
"stationId": "TESTXXYYSSWWLL",<br />
"islivestn": "y",<br />
"pbstarttm": "1631098029"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata (optional for DR) =====<br />
The Ad Metadata (if applicable) should be passed for each individual ad.<br />
<br />
Note: All metadata values should be passed as UTF-8 strings.<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of Ad || <code>"preroll"</code>, <code>"midroll"</code>, <code>"postroll"</code> <br> <code>"ad"</code> - If specific type can not be identified.|| ✓<br />
|-<br />
| assetid || unique ID assigned to Ad || custom<br>(no [[Special Characters]]) || ✓<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "unique_preroll_ad_id"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <code>"playhead"</code> || <br />
<br />
===== Handling Playhead =====<br />
<br />
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.<br />
<br />
'''General'''<br />
* Playhead position in seconds, must be passed as a whole number every 10 seconds. <br />
* The final playhead position should be sent before before sending "complete" event when content playback is complete. <br />
<br />
'''Live Stream'''<br />
* 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.<br />
<br />
'''VoD Stream'''<br />
* 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, ....<br />
<br />
'''End of an Asset'''<br />
* Final postion must be sent at the end of Content or Ad playback<br />
<br />
'''Ads'''<br />
* The final playhead position must be sent when switching from content to ad, or ad to content.<br />
* For Ad Pods, playhead must be called for each individual ad.<br />
* When content has resumed following a mid-roll ad break, the next playhead position must continue where the previous content segment left off.<br />
<br />
'''User Actions'''<br />
* 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.<br />
* PAUSE: When content is paused, send current playhead position and stop passing playhead position until content is resumed.<br />
* EXIT Stream: If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
|-<br />
| <code>"complete"</code> || The complete event must be sent when full playback of the content has completed . 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.<br />
|-<br />
| <code>"delete"</code> || The delete event is 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || ✓<br />
|-<br />
| <code>"position"</code> || playhead position in seconds or Unix time in seconds || <code>"300"</code> || ✓<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || ✓<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || ✓<br />
|-style="background-color:#d0f6f8;"<br />
| <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> || ✓<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000", //unix timestamp in milliseconds<br />
"sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle for VoD Stream =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle for VoD Stream - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
When playback is interrupted, the app needs to send delete immediately.<br />
<br />
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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = LsTYTmZQPwdchsNZkdtJp9lErjgAp1632729088 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sc-eucert.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"fpid": "U4EDwDcpvWIbguYVyjlhzS1v0eaov1631180980",<br />
"fpcrtm": "1631098029000"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2" // ad load flag,<br />
"subbrand": "c05",<br />
"stationId": "TESTXXYYSSWWLL",<br />
"islivestn": "y",<br />
"pbstarttm": "1631098029",<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000", //unix timestamp in milliseconds <br />
"sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609" // unique for each video play<br />
}<br />
<br />
// Append payload to URL<br />
function sendPayloadToNielsen() {<br />
var payloadStr = JSON.stringify(payload); // payload as string<br />
var imgPing = new Image();<br />
imgPing.onload = function() {<br />
// onload event, payload succesfull sent<br />
};<br />
imgPing.onerror = function() {<br />
// handle error i.e. wait and send again<br />
};<br />
imgPing.src = sessionURL+encodeURIComponent(payloadStr);<br />
}<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTP Response Code ====<br />
<br />
Confirm request was completed by viewing HTTP response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTP Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Review the Reference Implementation for VoD and Live Streams ==<br />
<br />
The Reference Implementation covers vod and Live use cases. <br />
It also covers DAI (Dynamic Ad Insertion) with preroll and postroll Ads.<br />
<br />
In order to start live stream select the checkbox "isLive" in the <code>Playback Settings</code> below the video player.<br />
<br />
Start the Reference Implementation for DK [https://nielsenonlinesupport.com/dk/cloudapi/index.htm?debug=true RefImplCloudAPIDK].<br />
<blockquote><br />
Review the Nielsen CloudAPI Call Sequence below the Video Player.<br />
</blockquote><br />
<br />
== Disclose Nielsen Privacy Statement ==<br />
<br />
In order to disclose Nielsen measurement privacy statement, please include the following items in your privacy policy:<br />
* A notice that the player includes third party measurement software that allows users to contribute to market research.<br />
* A link to the Nielsen Digital Measurement Privacy Policy located at https://sites.nielsen.com/priv/browser/dk/da/DigitalMeasurement.html .<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*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.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit, if the platform has the necessary exit callback events.<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTP Response ====<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sc-eucert.nmrodam.com/nmapi/v2/</code><br />
*Production: <code>https://capi-dmk.nmrodam.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://capi-dmk.nmrodam.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Sweden_Video_Cloud_API&diff=5690DCR Sweden Video Cloud API2022-03-14T19:22:50Z<p>LaMarHolmes: /* Event Types */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International DCR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
= DCR Integration Utilizing Cloud API =<br />
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.<br />
__TOC__<br />
==Prerequisites==<br />
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.<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 15%;" | Item<br />
! Description<br />
! Source<br />
|-style="background-color:#d0f6f8;"<br />
|| '''App ID (appid)''' || Unique ID assigned to the player/site and configured by product. || Provided by Nielsen<br />
|}<br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTP GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID. <br />
** '''Note: P prefix must be removed before adding it to the URL'''<br />
** Example App ID with P prefix: "PDF20695-XXXX-XXXX-XXXX-3E334133D917"<br />
** <code>https://sc-eucert.imrworldwide.com/nmapi/v2/DF20695-XXXX-XXXX-XXXX-3E334133D917/[sessionID]/a?b=[payload]</code><br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sc-eucert.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://capi-sw.imrworldwide.com/nmapi/v2/</code><br />
<br><br />
<br />
Please note that our Endpoints use TLS 1.2 and above, older devices using TLS 1.0 OR 1.1 is not compatible with the endpoints above. <br><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sc-eucert.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [Unix time in ms]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID and send EMM Ping===<br />
<br />
====Create Session ID====<br />
<br />
A unique Session ID <code>[sessionID]</code> must be created upon app launch and provided in the URL. This will allow the measurement to occur for the entire duration that a user is within the app.<br />
<br />
A Session ID needs to be completely unique so it is recommended to use our generation method example provided below to create unique alpha-numerical 29 characters + 10 characters UTC timestamp, 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.<br />
<br />
Session ID example: '''LsTYTmZQPwdchsNZkdtJp9lErjgAp1632729088'''<br />
<br><br />
<br />
<syntaxhighlight lang="javascript"><br />
'''// Create random GUID'''<br />
function buildGUID() {<br />
var UAIDbase62Characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";<br />
var UAIDpayloadLength = 29;<br />
<br />
function UAIDgetRandom62() {<br />
var r1;<br />
do {<br />
r1 = Math.floor(Math.random() * (16 * 62));<br />
} while (r1 > 61); <br />
return r1;<br />
}<br />
<br />
var uid = '';<br />
for (var a = 0; a < UAIDpayloadLength; a++) {<br />
uid += UAIDbase62Characters.charAt(UAIDgetRandom62());<br />
}<br />
uid += Math.floor(new Date().getTime() / 1000);<br />
return uid;<br />
}<br />
</syntaxhighlight><br />
<br><br />
<br />
Upon exiting the app, the session will need to be terminated using the delete event. <br><br />
Sessions will automatically expire after 30 minutes of cloud inactivity.<br />
<br />
====Send EMM Ping====<br />
An EMM Ping must be sent using the created unique Session ID <code>[sessionID]</code> upon start of the first stream playback.<br />
<syntaxhighlight lang="javascript"><br />
https://[sessionID].uaid.imrworldwide.com/<br />
</syntaxhighlight><br />
Also see [[#Review the Reference Implementation for VoD and Live Streams|Reference Implementation for VoD and Live Streams]] for your reference.<br />
<br />
===Create First Party ID===<br />
* An First Party ID <code>[fpid]</code> must be created and stored on the device. It is re-used until the expiration date or if the user has deleted it from the device storage.<br />
The default expiration date should be set to the equivalent of 180 days. <br />
* 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.<br />
<br />
===Create View Session ID for each Video Start===<br />
An View Session ID <code>[sessid]</code> must be created upon start of each stream playback, sessid is unique per video play.<br />
<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sc-eucert.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false",<br />
"fpid": "First Party ID",<br />
"fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"<br />
"hem_unknown" : "924899b875ea6767ab790bd2f4852345fcfec5d203c49be8e8..."<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "uniqueassetid_simulcast", // unique ID for video<br />
"userid": "fbd1a7a7d672a5fcf5cf5c55d8d9d0abbe3a4e0fa…", // SHA512 hashed userid<br />
"clientpassparam": "origcode=29", // Custom parameters passed<br />
"program": "Program Name leif-och-billy", // program name<br />
"title": "Episode Title S3 - EP1 en-ny-tjej-i-byn", // episode name<br />
"length": "3359", // content duration in seconds<br />
"playlisttitle": "barn", //playlist title<br />
"ispremiumcontent": "yes", //identify premium level content<br />
"isautoplay": "yes", //identify if autoplay is enabled<br />
"plugv": "1.0.1", //player version<br />
"playerv": "Sonic" // player identifier<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "E1UMBR1001", // unique ID for ad<br />
"length": "30", // ad duration in seconds<br />
"isprogrammatic": "yes",//identify if the ad is bought prommatic<br />
"isthirdpartyad": "yes",//identify if the ad is from third party ad server<br />
"adplatformorigin": "YuMe",//identity of ad origin <br />
"adidx": "1/5" //placement in ad break<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || ✓<br />
|-<br />
| apn || app name || custom || ✓<br />
|-<br />
| apv || app build version || custom || ✓<br />
|-<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || ✓<br />
|-<br />
|-<br />
| hem_unknown || Hashed email using SHA512. This email is used by MMS reach model. (required if login feature) || custom || ✓<br />
|-<br />
|-style="background-color:#d0f6f8;"<br />
| fpid || First Party ID || custom || ✓<br />
|-style="background-color:#d0f6f8;"<br />
| fpcrtm || Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds) || custom || ✓<br />
|-<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false",<br />
"fpid": "First Party ID",<br />
"fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"<br />
"hem_unknown" : "924899b875ea6767ab790bd2f4852345fcfec5d203c49be8e8..." //SHA512 hashed value<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Create Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br><br />
Please see the [[Sweden_SDK_Metadata|Metadata link]] for the full list of content and ad metadata.<br />
<br/><br />
'''Note:''' program and title metadata values should be passed as UTF-8 strings.<br />
<br />
===== Example Content Object =====<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "uniqueassetid",<br />
"length": "2600",<br />
"program": "program name",<br />
"title": "episode title"<br />
}</syntaxhighlight><br />
<br />
===== Create Ad Metadata =====<br />
The Ad Metadata (if applicable) should be passed for each individual ad.<br />
<br><br />
Please see the [[Sweden_SDK_Metadata|Metadata link]] for the full list of content and ad metadata.<br><br />
<br />
<br />
'''Note:''' All metadata values should be passed as UTF-8 strings.<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "unique_preroll_ad_id"<br />
}<br />
</syntaxhighlight><br />
<br/><br />
<blockquote> URL Character Limit: There is a URL character limit of 2K characters due to browser limitations. Exceeding this value could impair data delivery on particular browsers. </blockquote><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <code>"playhead"</code> || <br />
<br />
===== Handling Playhead =====<br />
<br />
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.<br />
<br />
'''General'''<br />
* Playhead position in seconds, must be passed as a whole number every 10 seconds. <br />
* The final playhead position should be sent before before sending "complete" event when content playback is complete. <br />
<br />
'''Live Stream'''<br />
* For Live streams, use Unix Time (in seconds) as the playhead position. Note that ad playheads must also use Unix Time for each single Ad in an Ad Pod.<br />
<br />
'''VoD Stream'''<br />
* 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, ....<br />
<br />
'''End of an Asset'''<br />
* Final postion must be sent at the end of Content or Ad playback<br />
<br />
'''Ads'''<br />
* The final playhead position must be sent when switching from content to ad, or ad to content.<br />
* For Ad Pods, playhead must be called for each individual ad.<br />
* When content has resumed following a mid-roll ad break, the next playhead position must continue where the previous content segment left off.<br />
<br />
'''User Actions'''<br />
* 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.<br />
* PAUSE: When content is paused, send current playhead position and stop passing playhead position until content is resumed.<br />
* EXIT Stream: If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
|-<br />
| <code>"complete"</code> || The complete event must be sent when full playback of the content has completed . 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.<br />
|-<br />
| <code>"delete"</code> || The delete event is 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || ✓<br />
|-<br />
| <code>"position"</code> || playhead position in seconds or Unix time in seconds || <code>"300"</code> || ✓<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || ✓<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || ✓<br />
|-style="background-color:#d0f6f8;"<br />
| <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> || ✓<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp in milliseconds<br />
"sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle for VoD Stream =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle for VoD Stream - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
<br />
'''Note:''' A session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = LsTYTmZQPwdchsNZkdtJp9lErjgAp1632729088 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sc-eucert.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false",<br />
"fpid": "U4EDwDcpvWIbguYVyjlhzS1v0eaov1631180980",<br />
"fpcrtm": "1631098029000"<br />
"hem_unknown" : "924899b875ea6767ab790bd2f4852345fcfec5d203c49be8e8..." //SHA512 hashed value<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"type": "content", // "content" for video<br />
"assetid": "uniqueassetid_simulcast", // unique ID for video<br />
"userid": "fbd1a7a7d672a5fcf5cf5c55d8d9d0abbe3a4e0fa…", // SHA512 hashed userid<br />
"clientpassparam": "origcode=29", // Custom parameters passed<br />
"program": "Program Name leif-och-billy", // program name<br />
"title": "Episode Title S3 - EP1 en-ny-tjej-i-byn", // episode name<br />
"length": "3359", // content duration in seconds<br />
"playlisttitle": "barn", //playlist title<br />
"ispremiumcontent": "yes", //identify premium level content<br />
"isautoplay": "yes", //identify if autoplay is enabled<br />
"plugv": "1.0.1", //player version<br />
"playerv": "Sonic" // player identifier<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123", // unique ID for ad<br />
"length": "3359", // ad duration in seconds<br />
"isprogrammatic": "yes",//identify if the ad is bought prommatic<br />
"isthirdpartyad": "yes",//identify if the ad is from third party ad server<br />
"adplatformorigin": "YuMe",//identity of ad origin <br />
"adidx": "1/5" //placement in ad break<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
"sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play<br />
}<br />
<br />
// Append payload to URL<br />
function sendPayloadToNielsen() {<br />
var payloadStr = JSON.stringify(payload); // payload as string<br />
var imgPing = new Image();<br />
imgPing.onload = function() {<br />
// onload event, payload succesfull sent<br />
};<br />
imgPing.onerror = function() {<br />
// handle error i.e. wait and send again<br />
};<br />
imgPing.src = sessionURL+encodeURIComponent(payloadStr);<br />
}<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTP Response Code ====<br />
<br />
Confirm request was completed by viewing HTTP response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTP Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
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.<br />
<br />
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.<br />
<br />
[[File:Nielsen Opt-Out.png|link=]]<br />
<br />
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). <br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement (Recommended Default Setting) || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "7be25cf9-8c40-5cc2-871e-19bf41940288",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "", //devId must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Privacy Information Template To Include In Opt-Out Screen =====<br />
<br />
<br />
Additionally, all applications must display the Nielsen privacy policy within their application, typically in the Settings/About screen of your application. The Nielsen privacy policy text is listed below.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process, and use. While our digital measurement products are not used to identify you in any way, they help us and our client's measure and analyze how consumers engage with media across online, mobile, and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt-out or opt into Nielsen measurement, please toggle your "Limit Ad Tracking" (or similar setting) on your device, or make the appropriate selection within the application's settings. If you have this app on more than one device, you will need to opt-out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit https://sites.nielsen.com/priv/browser/se/sv/optout.html <br />
<br />
</blockquote><br />
'''''Disclosure Template'''''<br />
<br />
Additionally, you must update the App description information from the App Distribution Store with the Nielsen Measurement disclosure below:<br />
<br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see https://sites.nielsen.com/priv/browser/se/sv/optout.html for more information.<br />
<br />
== Review the Reference Implementation for VoD and Live Streams ==<br />
<br />
The Reference Implementation covers vod and Live use cases. <br />
It also covers DAI (Dynamic Ad Insertion) with preroll and post-roll Ads.<br />
<br />
In order to start live stream select the checkbox "isLive" in the <code>Playback Settings</code> below the video player.<br />
<br />
Start the Reference Implementation for Sweden [http://nielsenonlinesupport.com/michel/sdkRefImplCloudDK/index.htm RefImplCloudAPISE].<br />
<blockquote><br />
Review the Nielsen CloudAPI Call Sequence below the Video Player.<br />
</blockquote><br />
<br />
== Disclose Nielsen Privacy Statement ==<br />
<br />
In order to disclose the Nielsen measurement privacy statement, please include the following items in your privacy policy:<br />
* A notice that the player includes third-party measurement software that allows users to contribute to market research with anonymous data.<br />
* A link to the Nielsen Digital Measurement Privacy Policy located at https://sites.nielsen.com/priv/browser/se/sv/optout.html .<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*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.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit, if the platform has the necessary exit callback events.<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTP Response ====<br />
*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.<br />
<br />
==== Opt-Out ====<br />
*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.<br />
*Test that the devId field is populated with a blank value if a user has elected to Opt-Out. For example: "devId": "",<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change the Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sc-eucert.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://capi-sw.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://capi-sw.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Sweden_Video_Cloud_API&diff=5685DCR Sweden Video Cloud API2022-03-14T19:14:34Z<p>LaMarHolmes: /* Interruption Scenarios */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International DCR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
= DCR Integration Utilizing Cloud API =<br />
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.<br />
__TOC__<br />
==Prerequisites==<br />
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.<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 15%;" | Item<br />
! Description<br />
! Source<br />
|-style="background-color:#d0f6f8;"<br />
|| '''App ID (appid)''' || Unique ID assigned to the player/site and configured by product. || Provided by Nielsen<br />
|}<br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTP GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID. <br />
** '''Note: P prefix must be removed before adding it to the URL'''<br />
** Example App ID with P prefix: "PDF20695-XXXX-XXXX-XXXX-3E334133D917"<br />
** <code>https://sc-eucert.imrworldwide.com/nmapi/v2/DF20695-XXXX-XXXX-XXXX-3E334133D917/[sessionID]/a?b=[payload]</code><br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sc-eucert.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://capi-sw.imrworldwide.com/nmapi/v2/</code><br />
<br><br />
<br />
Please note that our Endpoints use TLS 1.2 and above, older devices using TLS 1.0 OR 1.1 is not compatible with the endpoints above. <br><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sc-eucert.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [Unix time in ms]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID and send EMM Ping===<br />
<br />
====Create Session ID====<br />
<br />
A unique Session ID <code>[sessionID]</code> must be created upon app launch and provided in the URL. This will allow the measurement to occur for the entire duration that a user is within the app.<br />
<br />
A Session ID needs to be completely unique so it is recommended to use our generation method example provided below to create unique alpha-numerical 29 characters + 10 characters UTC timestamp, 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.<br />
<br />
Session ID example: '''LsTYTmZQPwdchsNZkdtJp9lErjgAp1632729088'''<br />
<br><br />
<br />
<syntaxhighlight lang="javascript"><br />
'''// Create random GUID'''<br />
function buildGUID() {<br />
var UAIDbase62Characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";<br />
var UAIDpayloadLength = 29;<br />
<br />
function UAIDgetRandom62() {<br />
var r1;<br />
do {<br />
r1 = Math.floor(Math.random() * (16 * 62));<br />
} while (r1 > 61); <br />
return r1;<br />
}<br />
<br />
var uid = '';<br />
for (var a = 0; a < UAIDpayloadLength; a++) {<br />
uid += UAIDbase62Characters.charAt(UAIDgetRandom62());<br />
}<br />
uid += Math.floor(new Date().getTime() / 1000);<br />
return uid;<br />
}<br />
</syntaxhighlight><br />
<br><br />
<br />
Upon exiting the app, the session will need to be terminated using the delete event. <br><br />
Sessions will automatically expire after 30 minutes of cloud inactivity.<br />
<br />
====Send EMM Ping====<br />
An EMM Ping must be sent using the created unique Session ID <code>[sessionID]</code> upon start of the first stream playback.<br />
<syntaxhighlight lang="javascript"><br />
https://[sessionID].uaid.imrworldwide.com/<br />
</syntaxhighlight><br />
Also see [[#Review the Reference Implementation for VoD and Live Streams|Reference Implementation for VoD and Live Streams]] for your reference.<br />
<br />
===Create First Party ID===<br />
* An First Party ID <code>[fpid]</code> must be created and stored on the device. It is re-used until the expiration date or if the user has deleted it from the device storage.<br />
The default expiration date should be set to the equivalent of 180 days. <br />
* 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.<br />
<br />
===Create View Session ID for each Video Start===<br />
An View Session ID <code>[sessid]</code> must be created upon start of each stream playback, sessid is unique per video play.<br />
<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sc-eucert.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false",<br />
"fpid": "First Party ID",<br />
"fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"<br />
"hem_unknown" : "924899b875ea6767ab790bd2f4852345fcfec5d203c49be8e8..."<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "uniqueassetid_simulcast", // unique ID for video<br />
"userid": "fbd1a7a7d672a5fcf5cf5c55d8d9d0abbe3a4e0fa…", // SHA512 hashed userid<br />
"clientpassparam": "origcode=29", // Custom parameters passed<br />
"program": "Program Name leif-och-billy", // program name<br />
"title": "Episode Title S3 - EP1 en-ny-tjej-i-byn", // episode name<br />
"length": "3359", // content duration in seconds<br />
"playlisttitle": "barn", //playlist title<br />
"ispremiumcontent": "yes", //identify premium level content<br />
"isautoplay": "yes", //identify if autoplay is enabled<br />
"plugv": "1.0.1", //player version<br />
"playerv": "Sonic" // player identifier<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "E1UMBR1001", // unique ID for ad<br />
"length": "30", // ad duration in seconds<br />
"isprogrammatic": "yes",//identify if the ad is bought prommatic<br />
"isthirdpartyad": "yes",//identify if the ad is from third party ad server<br />
"adplatformorigin": "YuMe",//identity of ad origin <br />
"adidx": "1/5" //placement in ad break<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || ✓<br />
|-<br />
| apn || app name || custom || ✓<br />
|-<br />
| apv || app build version || custom || ✓<br />
|-<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || ✓<br />
|-<br />
|-<br />
| hem_unknown || Hashed email using SHA512. This email is used by MMS reach model. (required if login feature) || custom || ✓<br />
|-<br />
|-style="background-color:#d0f6f8;"<br />
| fpid || First Party ID || custom || ✓<br />
|-style="background-color:#d0f6f8;"<br />
| fpcrtm || Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds) || custom || ✓<br />
|-<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false",<br />
"fpid": "First Party ID",<br />
"fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"<br />
"hem_unknown" : "924899b875ea6767ab790bd2f4852345fcfec5d203c49be8e8..." //SHA512 hashed value<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Create Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br><br />
Please see the [[Sweden_SDK_Metadata|Metadata link]] for the full list of content and ad metadata.<br />
<br/><br />
'''Note:''' program and title metadata values should be passed as UTF-8 strings.<br />
<br />
===== Example Content Object =====<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "uniqueassetid",<br />
"length": "2600",<br />
"program": "program name",<br />
"title": "episode title"<br />
}</syntaxhighlight><br />
<br />
===== Create Ad Metadata =====<br />
The Ad Metadata (if applicable) should be passed for each individual ad.<br />
<br><br />
Please see the [[Sweden_SDK_Metadata|Metadata link]] for the full list of content and ad metadata.<br><br />
<br />
<br />
'''Note:''' All metadata values should be passed as UTF-8 strings.<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "unique_preroll_ad_id"<br />
}<br />
</syntaxhighlight><br />
<br/><br />
<blockquote> URL Character Limit: There is a URL character limit of 2K characters due to browser limitations. Exceeding this value could impair data delivery on particular browsers. </blockquote><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <code>"playhead"</code> || <br />
<br />
===== Handling Playhead =====<br />
<br />
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.<br />
<br />
'''General'''<br />
* Playhead position in seconds, must be passed as a whole number every 10 seconds. <br />
* The final playhead position should be sent before before sending "complete" event when content playback is complete. <br />
<br />
'''Live Stream'''<br />
* For Live streams, use Unix Time (in seconds) as the playhead position. Note that ad playheads must also use Unix Time for each single Ad in an Ad Pod.<br />
<br />
'''VoD Stream'''<br />
* 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, ....<br />
<br />
'''End of an Asset'''<br />
* Final postion must be sent at the end of Content or Ad playback<br />
<br />
'''Ads'''<br />
* The final playhead position must be sent when switching from content to ad, or ad to content.<br />
* For Ad Pods, playhead must be called for each individual ad.<br />
* When content has resumed following a mid-roll ad break, the next playhead position must continue where the previous content segment left off.<br />
<br />
'''User Actions'''<br />
* 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.<br />
* PAUSE: When content is paused, send current playhead position and stop passing playhead position until content is resumed.<br />
* EXIT Stream: If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
|-<br />
| <code>"complete"</code> || The complete event must be sent when the playback of a content is terminated (i.e. full playback of content completed or switching to another content and therefore ending the current stream 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.<br />
|-<br />
| <code>"delete"</code> || The delete event is 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || ✓<br />
|-<br />
| <code>"position"</code> || playhead position in seconds or Unix time in seconds || <code>"300"</code> || ✓<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || ✓<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || ✓<br />
|-style="background-color:#d0f6f8;"<br />
| <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> || ✓<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp in milliseconds<br />
"sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle for VoD Stream =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle for VoD Stream - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
<br />
'''Note:''' A session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = LsTYTmZQPwdchsNZkdtJp9lErjgAp1632729088 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sc-eucert.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false",<br />
"fpid": "U4EDwDcpvWIbguYVyjlhzS1v0eaov1631180980",<br />
"fpcrtm": "1631098029000"<br />
"hem_unknown" : "924899b875ea6767ab790bd2f4852345fcfec5d203c49be8e8..." //SHA512 hashed value<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"type": "content", // "content" for video<br />
"assetid": "uniqueassetid_simulcast", // unique ID for video<br />
"userid": "fbd1a7a7d672a5fcf5cf5c55d8d9d0abbe3a4e0fa…", // SHA512 hashed userid<br />
"clientpassparam": "origcode=29", // Custom parameters passed<br />
"program": "Program Name leif-och-billy", // program name<br />
"title": "Episode Title S3 - EP1 en-ny-tjej-i-byn", // episode name<br />
"length": "3359", // content duration in seconds<br />
"playlisttitle": "barn", //playlist title<br />
"ispremiumcontent": "yes", //identify premium level content<br />
"isautoplay": "yes", //identify if autoplay is enabled<br />
"plugv": "1.0.1", //player version<br />
"playerv": "Sonic" // player identifier<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123", // unique ID for ad<br />
"length": "3359", // ad duration in seconds<br />
"isprogrammatic": "yes",//identify if the ad is bought prommatic<br />
"isthirdpartyad": "yes",//identify if the ad is from third party ad server<br />
"adplatformorigin": "YuMe",//identity of ad origin <br />
"adidx": "1/5" //placement in ad break<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
"sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play<br />
}<br />
<br />
// Append payload to URL<br />
function sendPayloadToNielsen() {<br />
var payloadStr = JSON.stringify(payload); // payload as string<br />
var imgPing = new Image();<br />
imgPing.onload = function() {<br />
// onload event, payload succesfull sent<br />
};<br />
imgPing.onerror = function() {<br />
// handle error i.e. wait and send again<br />
};<br />
imgPing.src = sessionURL+encodeURIComponent(payloadStr);<br />
}<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTP Response Code ====<br />
<br />
Confirm request was completed by viewing HTTP response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTP Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
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.<br />
<br />
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.<br />
<br />
[[File:Nielsen Opt-Out.png|link=]]<br />
<br />
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). <br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement (Recommended Default Setting) || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "7be25cf9-8c40-5cc2-871e-19bf41940288",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "", //devId must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Privacy Information Template To Include In Opt-Out Screen =====<br />
<br />
<br />
Additionally, all applications must display the Nielsen privacy policy within their application, typically in the Settings/About screen of your application. The Nielsen privacy policy text is listed below.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process, and use. While our digital measurement products are not used to identify you in any way, they help us and our client's measure and analyze how consumers engage with media across online, mobile, and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt-out or opt into Nielsen measurement, please toggle your "Limit Ad Tracking" (or similar setting) on your device, or make the appropriate selection within the application's settings. If you have this app on more than one device, you will need to opt-out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit https://sites.nielsen.com/priv/browser/se/sv/optout.html <br />
<br />
</blockquote><br />
'''''Disclosure Template'''''<br />
<br />
Additionally, you must update the App description information from the App Distribution Store with the Nielsen Measurement disclosure below:<br />
<br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see https://sites.nielsen.com/priv/browser/se/sv/optout.html for more information.<br />
<br />
== Review the Reference Implementation for VoD and Live Streams ==<br />
<br />
The Reference Implementation covers vod and Live use cases. <br />
It also covers DAI (Dynamic Ad Insertion) with preroll and post-roll Ads.<br />
<br />
In order to start live stream select the checkbox "isLive" in the <code>Playback Settings</code> below the video player.<br />
<br />
Start the Reference Implementation for Sweden [http://nielsenonlinesupport.com/michel/sdkRefImplCloudDK/index.htm RefImplCloudAPISE].<br />
<blockquote><br />
Review the Nielsen CloudAPI Call Sequence below the Video Player.<br />
</blockquote><br />
<br />
== Disclose Nielsen Privacy Statement ==<br />
<br />
In order to disclose the Nielsen measurement privacy statement, please include the following items in your privacy policy:<br />
* A notice that the player includes third-party measurement software that allows users to contribute to market research with anonymous data.<br />
* A link to the Nielsen Digital Measurement Privacy Policy located at https://sites.nielsen.com/priv/browser/se/sv/optout.html .<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*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.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit, if the platform has the necessary exit callback events.<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTP Response ====<br />
*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.<br />
<br />
==== Opt-Out ====<br />
*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.<br />
*Test that the devId field is populated with a blank value if a user has elected to Opt-Out. For example: "devId": "",<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change the Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sc-eucert.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://capi-sw.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://capi-sw.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Sweden_Video_Cloud_API&diff=5684DCR Sweden Video Cloud API2022-03-11T20:10:46Z<p>LaMarHolmes: /* Event Types */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International DCR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
= DCR Integration Utilizing Cloud API =<br />
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.<br />
__TOC__<br />
==Prerequisites==<br />
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.<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 15%;" | Item<br />
! Description<br />
! Source<br />
|-style="background-color:#d0f6f8;"<br />
|| '''App ID (appid)''' || Unique ID assigned to the player/site and configured by product. || Provided by Nielsen<br />
|}<br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTP GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID. <br />
** '''Note: P prefix must be removed before adding it to the URL'''<br />
** Example App ID with P prefix: "PDF20695-XXXX-XXXX-XXXX-3E334133D917"<br />
** <code>https://sc-eucert.imrworldwide.com/nmapi/v2/DF20695-XXXX-XXXX-XXXX-3E334133D917/[sessionID]/a?b=[payload]</code><br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sc-eucert.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://capi-sw.imrworldwide.com/nmapi/v2/</code><br />
<br><br />
<br />
Please note that our Endpoints use TLS 1.2 and above, older devices using TLS 1.0 OR 1.1 is not compatible with the endpoints above. <br><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sc-eucert.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [Unix time in ms]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID and send EMM Ping===<br />
<br />
====Create Session ID====<br />
<br />
A unique Session ID <code>[sessionID]</code> must be created upon app launch and provided in the URL. This will allow the measurement to occur for the entire duration that a user is within the app.<br />
<br />
A Session ID needs to be completely unique so it is recommended to use our generation method example provided below to create unique alpha-numerical 29 characters + 10 characters UTC timestamp, 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.<br />
<br />
Session ID example: '''LsTYTmZQPwdchsNZkdtJp9lErjgAp1632729088'''<br />
<br><br />
<br />
<syntaxhighlight lang="javascript"><br />
'''// Create random GUID'''<br />
function buildGUID() {<br />
var UAIDbase62Characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";<br />
var UAIDpayloadLength = 29;<br />
<br />
function UAIDgetRandom62() {<br />
var r1;<br />
do {<br />
r1 = Math.floor(Math.random() * (16 * 62));<br />
} while (r1 > 61); <br />
return r1;<br />
}<br />
<br />
var uid = '';<br />
for (var a = 0; a < UAIDpayloadLength; a++) {<br />
uid += UAIDbase62Characters.charAt(UAIDgetRandom62());<br />
}<br />
uid += Math.floor(new Date().getTime() / 1000);<br />
return uid;<br />
}<br />
</syntaxhighlight><br />
<br><br />
<br />
Upon exiting the app, the session will need to be terminated using the delete event. <br><br />
Sessions will automatically expire after 30 minutes of cloud inactivity.<br />
<br />
====Send EMM Ping====<br />
An EMM Ping must be sent using the created unique Session ID <code>[sessionID]</code> upon start of the first stream playback.<br />
<syntaxhighlight lang="javascript"><br />
https://[sessionID].uaid.imrworldwide.com/<br />
</syntaxhighlight><br />
Also see [[#Review the Reference Implementation for VoD and Live Streams|Reference Implementation for VoD and Live Streams]] for your reference.<br />
<br />
===Create First Party ID===<br />
* An First Party ID <code>[fpid]</code> must be created and stored on the device. It is re-used until the expiration date or if the user has deleted it from the device storage.<br />
The default expiration date should be set to the equivalent of 180 days. <br />
* 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.<br />
<br />
===Create View Session ID for each Video Start===<br />
An View Session ID <code>[sessid]</code> must be created upon start of each stream playback, sessid is unique per video play.<br />
<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sc-eucert.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false",<br />
"fpid": "First Party ID",<br />
"fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"<br />
"hem_unknown" : "924899b875ea6767ab790bd2f4852345fcfec5d203c49be8e8..."<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "uniqueassetid_simulcast", // unique ID for video<br />
"userid": "fbd1a7a7d672a5fcf5cf5c55d8d9d0abbe3a4e0fa…", // SHA512 hashed userid<br />
"clientpassparam": "origcode=29", // Custom parameters passed<br />
"program": "Program Name leif-och-billy", // program name<br />
"title": "Episode Title S3 - EP1 en-ny-tjej-i-byn", // episode name<br />
"length": "3359", // content duration in seconds<br />
"playlisttitle": "barn", //playlist title<br />
"ispremiumcontent": "yes", //identify premium level content<br />
"isautoplay": "yes", //identify if autoplay is enabled<br />
"plugv": "1.0.1", //player version<br />
"playerv": "Sonic" // player identifier<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "E1UMBR1001", // unique ID for ad<br />
"length": "30", // ad duration in seconds<br />
"isprogrammatic": "yes",//identify if the ad is bought prommatic<br />
"isthirdpartyad": "yes",//identify if the ad is from third party ad server<br />
"adplatformorigin": "YuMe",//identity of ad origin <br />
"adidx": "1/5" //placement in ad break<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || ✓<br />
|-<br />
| apn || app name || custom || ✓<br />
|-<br />
| apv || app build version || custom || ✓<br />
|-<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || ✓<br />
|-<br />
|-<br />
| hem_unknown || Hashed email using SHA512. This email is used by MMS reach model. (required if login feature) || custom || ✓<br />
|-<br />
|-style="background-color:#d0f6f8;"<br />
| fpid || First Party ID || custom || ✓<br />
|-style="background-color:#d0f6f8;"<br />
| fpcrtm || Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds) || custom || ✓<br />
|-<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false",<br />
"fpid": "First Party ID",<br />
"fpcrtm": "Creation Time (UTC) of the First Party ID (Unix Timestamp in milliseconds)"<br />
"hem_unknown" : "924899b875ea6767ab790bd2f4852345fcfec5d203c49be8e8..." //SHA512 hashed value<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Create Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br><br />
Please see the [[Sweden_SDK_Metadata|Metadata link]] for the full list of content and ad metadata.<br />
<br/><br />
'''Note:''' program and title metadata values should be passed as UTF-8 strings.<br />
<br />
===== Example Content Object =====<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "uniqueassetid",<br />
"length": "2600",<br />
"program": "program name",<br />
"title": "episode title"<br />
}</syntaxhighlight><br />
<br />
===== Create Ad Metadata =====<br />
The Ad Metadata (if applicable) should be passed for each individual ad.<br />
<br><br />
Please see the [[Sweden_SDK_Metadata|Metadata link]] for the full list of content and ad metadata.<br><br />
<br />
<br />
'''Note:''' All metadata values should be passed as UTF-8 strings.<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "unique_preroll_ad_id"<br />
}<br />
</syntaxhighlight><br />
<br/><br />
<blockquote> URL Character Limit: There is a URL character limit of 2K characters due to browser limitations. Exceeding this value could impair data delivery on particular browsers. </blockquote><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <code>"playhead"</code> || <br />
<br />
===== Handling Playhead =====<br />
<br />
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.<br />
<br />
'''General'''<br />
* Playhead position in seconds, must be passed as a whole number every 10 seconds. <br />
* The final playhead position should be sent before before sending "complete" event when content playback is complete. <br />
<br />
'''Live Stream'''<br />
* For Live streams, use Unix Time (in seconds) as the playhead position. Note that ad playheads must also use Unix Time for each single Ad in an Ad Pod.<br />
<br />
'''VoD Stream'''<br />
* 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, ....<br />
<br />
'''End of an Asset'''<br />
* Final postion must be sent at the end of Content or Ad playback<br />
<br />
'''Ads'''<br />
* The final playhead position must be sent when switching from content to ad, or ad to content.<br />
* For Ad Pods, playhead must be called for each individual ad.<br />
* When content has resumed following a mid-roll ad break, the next playhead position must continue where the previous content segment left off.<br />
<br />
'''User Actions'''<br />
* 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.<br />
* PAUSE: When content is paused, send current playhead position and stop passing playhead position until content is resumed.<br />
* EXIT Stream: If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
|-<br />
| <code>"complete"</code> || The complete event must be sent when the playback of a content is terminated (i.e. full playback of content completed or switching to another content and therefore ending the current stream 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.<br />
|-<br />
| <code>"delete"</code> || The delete event is 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || ✓<br />
|-<br />
| <code>"position"</code> || playhead position in seconds or Unix time in seconds || <code>"300"</code> || ✓<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || ✓<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || ✓<br />
|-style="background-color:#d0f6f8;"<br />
| <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> || ✓<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp in milliseconds<br />
"sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle for VoD Stream =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle for VoD Stream - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
When playback is interrupted, the app needs to send delete immediately.<br />
<br />
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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = LsTYTmZQPwdchsNZkdtJp9lErjgAp1632729088 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sc-eucert.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false",<br />
"fpid": "U4EDwDcpvWIbguYVyjlhzS1v0eaov1631180980",<br />
"fpcrtm": "1631098029000"<br />
"hem_unknown" : "924899b875ea6767ab790bd2f4852345fcfec5d203c49be8e8..." //SHA512 hashed value<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"type": "content", // "content" for video<br />
"assetid": "uniqueassetid_simulcast", // unique ID for video<br />
"userid": "fbd1a7a7d672a5fcf5cf5c55d8d9d0abbe3a4e0fa…", // SHA512 hashed userid<br />
"clientpassparam": "origcode=29", // Custom parameters passed<br />
"program": "Program Name leif-och-billy", // program name<br />
"title": "Episode Title S3 - EP1 en-ny-tjej-i-byn", // episode name<br />
"length": "3359", // content duration in seconds<br />
"playlisttitle": "barn", //playlist title<br />
"ispremiumcontent": "yes", //identify premium level content<br />
"isautoplay": "yes", //identify if autoplay is enabled<br />
"plugv": "1.0.1", //player version<br />
"playerv": "Sonic" // player identifier<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123", // unique ID for ad<br />
"length": "3359", // ad duration in seconds<br />
"isprogrammatic": "yes",//identify if the ad is bought prommatic<br />
"isthirdpartyad": "yes",//identify if the ad is from third party ad server<br />
"adplatformorigin": "YuMe",//identity of ad origin <br />
"adidx": "1/5" //placement in ad break<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
"sessid": "xxxjavd6wzirm93xb95uxjy1ac5wu1627638609", // unique for each video play<br />
}<br />
<br />
// Append payload to URL<br />
function sendPayloadToNielsen() {<br />
var payloadStr = JSON.stringify(payload); // payload as string<br />
var imgPing = new Image();<br />
imgPing.onload = function() {<br />
// onload event, payload succesfull sent<br />
};<br />
imgPing.onerror = function() {<br />
// handle error i.e. wait and send again<br />
};<br />
imgPing.src = sessionURL+encodeURIComponent(payloadStr);<br />
}<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTP Response Code ====<br />
<br />
Confirm request was completed by viewing HTTP response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTP Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
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.<br />
<br />
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.<br />
<br />
[[File:Nielsen Opt-Out.png|link=]]<br />
<br />
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). <br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement (Recommended Default Setting) || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "7be25cf9-8c40-5cc2-871e-19bf41940288",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "", //devId must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Privacy Information Template To Include In Opt-Out Screen =====<br />
<br />
<br />
Additionally, all applications must display the Nielsen privacy policy within their application, typically in the Settings/About screen of your application. The Nielsen privacy policy text is listed below.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process, and use. While our digital measurement products are not used to identify you in any way, they help us and our client's measure and analyze how consumers engage with media across online, mobile, and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt-out or opt into Nielsen measurement, please toggle your "Limit Ad Tracking" (or similar setting) on your device, or make the appropriate selection within the application's settings. If you have this app on more than one device, you will need to opt-out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit https://sites.nielsen.com/priv/browser/se/sv/optout.html <br />
<br />
</blockquote><br />
'''''Disclosure Template'''''<br />
<br />
Additionally, you must update the App description information from the App Distribution Store with the Nielsen Measurement disclosure below:<br />
<br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see https://sites.nielsen.com/priv/browser/se/sv/optout.html for more information.<br />
<br />
== Review the Reference Implementation for VoD and Live Streams ==<br />
<br />
The Reference Implementation covers vod and Live use cases. <br />
It also covers DAI (Dynamic Ad Insertion) with preroll and post-roll Ads.<br />
<br />
In order to start live stream select the checkbox "isLive" in the <code>Playback Settings</code> below the video player.<br />
<br />
Start the Reference Implementation for Sweden [http://nielsenonlinesupport.com/michel/sdkRefImplCloudDK/index.htm RefImplCloudAPISE].<br />
<blockquote><br />
Review the Nielsen CloudAPI Call Sequence below the Video Player.<br />
</blockquote><br />
<br />
== Disclose Nielsen Privacy Statement ==<br />
<br />
In order to disclose the Nielsen measurement privacy statement, please include the following items in your privacy policy:<br />
* A notice that the player includes third-party measurement software that allows users to contribute to market research with anonymous data.<br />
* A link to the Nielsen Digital Measurement Privacy Policy located at https://sites.nielsen.com/priv/browser/se/sv/optout.html .<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*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.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit, if the platform has the necessary exit callback events.<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTP Response ====<br />
*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.<br />
<br />
==== Opt-Out ====<br />
*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.<br />
*Test that the devId field is populated with a blank value if a user has elected to Opt-Out. For example: "devId": "",<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change the Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sc-eucert.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://capi-sw.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://capi-sw.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DAR_Audit_Ping&diff=5673DAR Audit Ping2022-03-01T23:17:39Z<p>LaMarHolmes: Created page with "== Introduction == The Nielsen Server-to-Server (S2S) solution needs audit pings for audience validation. The audit pings are https requests that are fired at least once per..."</p>
<hr />
<div>== Introduction ==<br />
<br />
The Nielsen Server-to-Server (S2S) solution needs audit pings for audience validation. The audit pings are https requests that are fired at least once per session. It primarily contains URL parameters with a randomly generated Session Identifier, Integration Identifier, and a timestamp that is matched to the server-side traffic.<br />
<br />
The end user device makes a request to Nielsen Collections servers at least once per Session. Sessions are defined as continuous interaction with the application, with gaps that do not exceed contiguous content consumption of 30 minutes or greater. The Audit pings are required to fire only once per Session, ideally at the beginning of the Session or upon first ad exposure. Audit Pings may optionally fire more often, for example: fired upon each ad exposure if preferred.<br />
<br />
Audit Pings are intended to be as light-weight, generic as possible, and contain no personal identifiers, campaign information, or advertisement metadata. The following two primary technical purposes of the audit ping are:<br />
<br />
# to enable Nielsen to make a connection between metered Nielsen panelists and the Census data received via the DAR S2S integration. This ping provides a signal that Nielsen streaming meters and mobile meter devices can intercept the Session IDs<br />
# as a secondary mechanism to monitor the health of the S2S DAR measurement. If DAR S2S measurement fails in some way, Nielsen can detect a disparity between the trends in volume from the Audit pings and Census data. Anomalous detected behavior will prompt Nielsen to investigate. For example: Audit Pings without corresponding DAR S2S measurement or the converse.<br />
<br />
== Ping Structure ==<br />
<br />
Requests should be executed with following convention structure:<br />
https://audit.imrworldwide.com/cgi-bin/gn?prd=audit&{query parameter list} (see table below)<br />
(Please note that this URL may require updates in response to changes in the market.)<br />
<br />
The Audit Ping will carry all parameters in the matrix later in this document. Under normal operating circumstances, the Nielsen collection system will return the following response codes:<br />
* 302: A redirect to another Nielsen domain, used for the purpose of generating a URL compatible with Nielsen streaming meters<br />
* 200: The ping was successfully received, inspect traffic to ensure no CORS error<br />
<br />
== Audit Ping Implementation Details ==<br />
<br />
* SessionIDs Ideally when the application is initiated, a SessionID is also created, optionally upon first ad exposure<br />
* Audit Pings will be fired at least every time a SessionID is created<br />
* It is permissible for Audit Pings to fire more frequently than once per session (for example, upon each ad exposure, or page change, etc.)<br />
* It is permissible for SessionIDs to change within a session, so long as the Audit Ping is fired again ensuring that the DAR S2S ImpID parameter reflects the same new SessionID<br />
* For security reasons, downstream servers reject cross-origin HTTP requests with preflight. To ensure that audit ping requests are accepted, allowable Content-Types like "text/plain" in simple GET requests ensure that preflight requests are not invoked, which is the preferred behavior.<br />
<br />
<br />
{| class="wikitable" <br />
|- <br />
! PARAM<br />
! DESCRIPTION<br />
! MANDATORY<br />
! Specified By<br />
! Format Example<br />
|-<br />
| intid<br />
| Single ID assigned per integration for all audit pings across platforms<br />
| Yes<br />
| Nielsen<br />
| a9ddf15ea054ea415718767ea6<br />
|-<br />
| apid<br />
| Server App ID assigned by Nielsen<br />
| Only required for content measurement<br />
| Nielsen<br />
| Alphanumeric application identifier assigned by Nielsen by platform<br />
|-<br />
| sessionid<br />
| Unique id generated when video player is instantiated<br />
| Yes<br />
| Client<br />
| Format: alphanumeric, Example: 16 char guid<br />
|-<br />
| product<br />
| Indicates which product audit ping content corresponds to<br />
| Yes<br />
| Client<br />
| Format: alphanumeric, Example: “dar”, “dcr”, “dtvr”<br />
|-<br />
| createtm<br />
| Time the ping was fired<br />
| Yes<br />
| Client<br />
| Format: UnixTime “1643858542”<br />
|}<br />
<br />
'''Generic Ping Format:'''<br />
<syntaxhighlight><br />
https://audit.imrworldwide.com/cgi-bin/gn?prd=audit<br />
&intid=<Integration id>&apid=<App id>&sessionid=<Session Id>&product=<dar>&createtm=<><br />
</syntaxhighlight><br />
<br />
<br />
'''Audit Ping Example:'''<br />
<syntaxhighlight><br />
https://audit.imrworldwide.com/cgi-bin/gn?prd=audit&intid=a9ddf15ea054ea415718767ea6&apid=FC984EC1-E044-B465-E040-070AAD3173A1&sessionid=2576459933726989&product=dar&createtm=1643858542<br />
</syntaxhighlight><br />
<br />
<br />
== DAR Ping Implementation Details ==<br />
<br />
For S2S DAR Tags, a new Impression ID parameter specified as "&impid" that exactly matches the SessionID included in the Audit Pings.<br />
<br />
'''Example DAR Ping:'''<br />
<syntaxhighlight><br />
https://secure-us.imrworldwide.com/cgi-bin/m?ci=us-201234h&cg=0[...]&impid=2576459933726989&rnd=164403011<br />
</syntaxhighlight></div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DAR_Tag_Implementation_Guide&diff=5662DAR Tag Implementation Guide2022-03-01T17:12:56Z<p>LaMarHolmes: /* Unified ID */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
<br />
== Introduction ==<br />
<br />
Nielsen Digital Ad Ratings is a measurement platform for online advertising campaigns. The platform provides a clear view of the true audience of a campaign, including '''Reach''', '''Frequency''', and '''GRP''' statistics by audience demographic group.<br />
<br />
The key innovation of the platform is the inclusion of demographic data from leading web publishers to attach actual user demographics to ad impressions.<br />
<br />
The diagram below summarizes how the Nielsen tag measures the ad campaign:<br />
# Advertiser places ads on one or more websites<br />
#Website displays ad to a user<br />
#Nielsen tag counts impressions and controls redirect to the Data Enrichment Provider<br />
[[File:dar-image2.png|900px]]<br />
<br />
<br />
=== Support for Other Nielsen Ad Effectiveness Products ===<br />
<br />
The tag used for Nielsen Digital Ad Ratings is compatible for all Nielsen Ad Effectiveness products, including (but not limited to) Brand Effect Extended View, Response Effect, and Sales Effect.<br />
<br />
=== User Experience ===<br />
<br />
The tags described in this document are used only to measure audience exposure to advertisements; they do not launch a survey, and have no impact on the user experience. Typical response time for the tag is on par with industry standards and because the code executed is simple and fires after the ad loads, they are transparent to the user.<br />
<br />
For further information on survey-based products, or any other products, please contact your Client Services Manager.<br />
__TOC__<br />
<br />
== Available Tag Versions ==<br />
<br />
The Nielsen Digital Ad Ratings system offers 2 basic types of ad tags<br />
<br />
* '''IMAGE (1X1) Pixel'''<br />
This is the simplest version of the tag, generally for use by clients who cannot accept JavaScript format tags or have limited options for implementation. Itincludes encryption, but does not utilize referrer masking.<br />
<br />
* '''JavaScript Tag'''<br />
This is a more complex tag which includes encryption and masking of referrer site via a script call. This Tag may also be used to measure Viewability metrics.<br />
There may be additional functionality offered by this format in future releases as well.<br />
* '''Ad Networks''' This tag includes additional functionality to scrape the URL of the hosting website if associated to an ad network within the Nielsen system. Keep in mind URLs captured will only be used for “site adjustment factors” and not be included in any reporting<br />
<br />
<blockquote>'''NOTE''' - Both tag types support macros and are available in secure and non-secure formats. Please reach out to your Nielsen Technical Account Manager for additional information.</blockquote><br />
<br />
While the IMAGE pixels are easiest to implement, the JavaScript versions are recommended because they provide the highest level of confidentiality by masking the source of the ad from being viewable by Data Providers. Some situations may not afford use of JavaScript and in those cases, the pixel version will be recommended. Note that in many cases the referrer is cast as the ad server due to the nature of being served inside iframes, so the “masking” here is extraneous.<br />
<br />
=== Tag Examples ===<br />
<br />
<br><br />
'''IMAGE Pixel Tag''' (Static example)<br />
<syntaxhighlight lang="javascript"><br />
<img src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3&ca=cmpXXXX&cr=&pc=plcXXXX&r=[timestamp]"<br />
width="1" height="1" alt=""/><br />
</syntaxhighlight><br />
<br />
'''IMAGE Pixel Tag''' (Macro example)<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"><br />
</script><br />
</syntaxhighlight><br />
<br />
'''JavaScript Tag''' (Static example)<br />
<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3mr=1&ty=js&ca=cmpXXXX&cr=&pc=plcXXXX&r=[timestamp]"<br />
></script><br />
</syntaxhighlight><br />
<br />
'''JavaScript Tag''' (Macro example)<br />
<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"></<br />
script><br />
</syntaxhighlight><br />
<br><br />
<br />
The Nielsen Digital Ad Ratings system also features the ability to record Viewability information such as: How long an Ad has been visible on the screen, and what portion on the Ad. This is an additional feature that can be purchased from your Nielsen Client Services Representative.<br />
<br />
Viewability for display ads can ONLY be offered through the JavaScript tag. If you select this service, the following is an example of the tag that will be provided to you by the Nielsen Digital Implementation Team:<br />
<br />
'''JavaScript with Viewability for display ads:'''<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"></<br />
script><br />
</syntaxhighlight><br />
<br />
<blockquote>The above tag is just examples and should not be placed in any live site or ad server. You will be provided with tags specifically designed for your media plan/campaign or be able to download tags after creation in CMI (Campaign Management Interface)</blockquote><br />
<br />
== Standard DAR Tag ==<br />
The DAR tag is available as a 1x1 pixel. The following pixel/tag parameters must be specified for all DAR tags, 1x1, regardless of implementation type: browser, mobile browser, mobile app or connected device.<br />
<br />
{| class="wikitable" <br />
|-<br />
! Tag Parameter<br />
! Description<br />
|-<br />
| CI<br />
| Client ID: the ID that is associated with the DAR account that processed tag data is associated with. Will always be hardcoded to a Nielsen generated value that comes from the Nielsen campaign management system<br />
|- style="background-color:#eff8ef;"<br />
| AM<br />
| Ad Server: an ad server participating on the campaign media-plan. This is an internal Nielsen generated value when the ad server is indicated on the campaign during setup<br />
|-<br />
| CA<br />
| Campaign Id: this is the ID associated with your DAR campaign. Unless you are creating and managing the Nielsen campaign via the DAR Tag API, then this parameter value will always be generated from the Nielsen campaign management system. Note: often maps to a media-plan I/O Id<br />
|- style="background-color:#eff8ef;"<br />
| CR<br />
| Creative Id: DAR does not currently report at the creative level; can be hard coded ad server id or associated with a macro expansion<br />
|-<br />
| PC<br />
| Placement Id: can be generated by the ad server via macro expansion or generated by the Nielsen campaign management system. Note: often maps to one of Ad Unit Id, Line Item Id or Video Ad Id<br />
|- style="background-color:#eff8ef;"<br />
| CE<br />
| Site Id: the Id that identifies a publisher site that the placement needs to be mapped to. Maps into the Nielsen MarketView database. Note: can be hardcoded to a pre-registered ad server site id in the Nielsen system or a macro expansion where more than one pre-existing site ids have been made known to Nielsen<br />
|-<br />
| R<br />
| Cachebuster (web): timestamp / random number. Generated by ad server<br />
|- style="background-color:#eff8ef;"<br />
| AT<br />
| Fixed value: “view”<br />
|-<br />
| RT<br />
| Fixed value: “banner”<br />
|- style="background-color:#eff8ef;"<br />
| ST<br />
| Fixed value: “image”<br />
|}<br />
<blockquote> Do not URL encode the values</blockquote><br />
<br />
== Additional Parameters ==<br />
In this section we describe the additional parameters that the DAR tag can support, specifically Hashed Email, UID2 values, along with Page URL and Bundle Identifier if available. Please work with your Nielsen Technical Account Manager on deciding which of the following parameters to append to the standard DAR tag. <br />
<br />
'''Web Browser DAR tag (cookie based persons identification)'''<br />
<br />
[https://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=nlsn_plc0001&ce=000&r=34245454 https://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=<siteid>&r=<timestamp>]<br />
<br />
'''Web Browser PLUS tag'''<br />
<br />
[http://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=554554_plc0001&ce=0000 http://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=0000]&hem_sha256=<value>&uid2=<value>&uid_token=<value>&si=<value>c68=bndlid,com.tam.nielsen.com<br />
<br />
=== HEM Support (Hashed Email) ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"| Hashed Email <br />
| User’s email address that has been run through a hashing algorithm (e.g. SHA256, MD5, SHA1) </br> to create a unique string. If a client is unable to determine hashing type, they should pass using &hem_unknown parameter.<br />
|style="width: 20%"|<code>&hem_unknown</br>&hem_sha256</br>&hem_md5</br>&hem_sha1</code><br />
|}<br />
<br />
<blockquote>Please use the parameter that matches your hashing algorithm.<br> For example, if you are using sha256 to encode the email address, then use <code>hem_sha256={encrypted_value_here}</code><br />
</blockquote><br />
Example:<br />
<syntaxhighlight lang="javascript"><br />
hem_sha256=tMmiiTI7IaAcPpQPFQ65uMVCWH8av9jw4cwf/F5HVRQ=<br />
</syntaxhighlight><br />
<br />
=== Unified ID ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"| Unified ID 2.0<br />
| An identifier based on a user’s verifiable PII (e.g. hashed email). UID2.0 was initially created by The Trade Desk (TTD)</br> and is now managed by Prebid. For more information on UID2.0 : https://github.com/UnifiedID2/uid2docs<br />
| &uid2<br />
|}<br />
<br />
Example:<br />
<syntaxhighlight lang="javascript"><br />
uid2=MTKVpUAzwYAPnHrtfE0wlINOMzhU7UUEjjVdCdRu63k=<br />
</syntaxhighlight><br />
<br />
=== Page and Bundle ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"|Page URL<br />
| style="width: 65%"| Canonical URL of the content where the Ad creative is served. (e.g. https://example.com/news/tech/article.html) The parameter value has to be encoded with JavaScript’s encodeURIComponent() method or equivalent. <br />Example: si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
| &si<br />
|-<br />
| App Bundle ID<br />
| The app’s unique bundle ID (e.g. com.example.myapp). The ID can be used to look up the App in Apple’s App Store</br> or the Google Play Store. References:https://developer.android.com/studio/build/application-idhttps://developer.apple.com/documentation/appstoreconnectapi/bundle_ids<br />
| &c68=bndlid,<br />
|}<br />
<br />
Example:<br />
<syntaxhighlight><br />
si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
c68=bndlid,com.tam.nielsen.com<br />
</syntaxhighlight><br />
<br />
== Supported Creative Types ==<br />
<br />
For consistency, Nielsen recommends tagging as much of the campaign creative types as possible, including site-served elements. '''Note:''' Nielsen may need to review/test on a case-by-case basis.<br />
<br />
Nielsen Digital Ad Ratings supports banner ads, rich media and video units that are capable of being tagged with a 3rd party tracking pixel.<br />
<blockquote>Some examples of non-standard campaign items that may be tagged include:<br />
* microsite pages<br />
* site “skins’”<br />
* online mini-games<br />
* streaming video<br />
* pre-roll video banners<br />
</blockquote><br />
Most often, these items will need to be site served and our pixel will need to be provided to the site to implement directly.<br />
<blockquote>The following are items not tagged:<br />
* click command/text links<br />
* default/backup ads in a 3rd party ad server<br />
* static ‘logo’ creatives<br />
</blockquote><br />
<br />
Digital Ad Ratings Viewability Solution: All standard ad units listed under [http://www.iab.net/displayguidelines Universal Ad Package (UAP)] on are supported for Viewability.<br />
<br />
Placements and sites that cannot support JavaScript cannot support Viewability.<br />
<br />
'''‘Best Practices’ for Video Tags:''' Nielsen recommends all video tags be deployed as close to the beginning of the video stream as possible (post buffer).<br />
Placements delivering to Flash creative should have our tag implemented within the Flash code.<br />
<br />
== How the Tag Works ==<br />
<br />
The following describes the masked javascript version of the tag. <br><br />
For the non-masked pixel version of the tag, steps 5-8 would be collapsed to just 2 steps.<br />
<br />
[[File:image3-dar.png|right|500px]]<br />
# End-user uses her web browser to visit a website that contains an ad creative being measured by Nielsen.<br />
# Website sends web page back to end-user. (Web page contains HTML describing web content & ads)<br />
# End-user’s web browser requests the ad creative from Ad Server<br />
# Ad Server sends an iframe ad creative back to the end-user which contains the Nielsen measurement tag<br />
# End-user’s web browser makes a request to the Nielsen servers.<br />
## The tag’s HTTP request contains a campaign ID and placement, which is collected by Nielsen<br />
## The Nielsen system checks the user’s machine for an opt-out cookie – if one exists the process ends here<br />
## The Nielsen system checks to see if the campaign value in the tag was selected for Viewability. If so it downloads the Integral Ad Science tag to the end-user’s browser.<br />
# Nielsen server sends JavaScript code back to end-user’s web browser, including a 1x1 pixel.<br />
# End-user’s web browser executes JavaScript code and makes an iframe request to Nielsen server to enable the “referrer masking redirect”<br />
# Nielsen server sends an HTML message to the end-user’s web browser.<br />
# End-user’s web browser executes HTML and requests a 1x1 pixel from the Data Provider using Nielsen server information as the HTTP referrer – thus masking the Website’s information<br />
## The campaign ID and placement ID are passed through to Data Provider in an encrypted format<br />
# If Viewability is enabled the JavaScript will download a Javascript tag that calls the viewability vendor (either Nielsen or 3rd Party) to begin tracking inview metrics.<br />
# Data Provider responds with a 1x1 pixel. End process.<br />
<br />
== Share Your Delivered Impressions ==<br />
<br />
'''Why the Media Plan is Needed'''<br />
<br />
Knowing the delivered impressions also helps Nielsen run automated QA checks, for example triggering alerts when data does not appear for a placement on an expected date. This ensures overall quality, and reduces errors in the tagging process.<br />
<br />
It is the responsibility of the client to send Nielsen an impression delivery report, generally known as the “ad server report.” Nielsen can provide the client with a template with the inputs required to complete the quality checks. If the client does not send these reports, Nielsen will not be able to complete the quality checks. Below are instructions on how to send these reports to Nielsen.<br />
<br />
'''How to Share Your Delivered impressions'''<br />
<br />
Set up an automated daily report from your ad server containing Site Name, Site ID, Placement Name, Placement ID, and data date.<br />
<br />
A secondary method to share your media plan information is to grant Nielsen “Reporting access” to your campaign in the designated ad server (such as DCM). To do this, simply grant the login [http://mailto:clientreporting@nielsen.com clientreporting@nielsen.com] access. In doing so Nielsen can directly access your media plan information, which enables us to check for updates, and reconcile any<br /><br />
discrepancies.<br />
<br />
<blockquote>Please note that Nielsen is currently in discussions with several leading Ad Servers regarding direct integration between Nielsen and the ad server platforms. Once completed this could someday enable Nielsen to retrieve Media Plans on a completed automated basis.<br />
</blockquote><br />
<br />
== Apply the Tag ==<br />
=== Tag Generation ===<br />
<br />
Your Nielsen representative will walk you through the Campaign Management Interface so that you can download tags at will at any point in the campaign.<br />
<br />
Nielsen supports macro-based tag generation for several major ad servers. Nielsen’s Technical Account Manager (TAM) can assist you in leveraging macro-based tags.<br />
<br />
=== Tag Application ===<br />
<br />
Apply the tag according to the 3rd party tracking pixel specifications of your ad server. If additional guidance is needed, please consult with the Technical Account Manager (TAM) for more specific instructions or recommendations, if available.<br />
<br />
== Special Note for Video Tags ==<br />
Nielsen’s recommended “Best Practice” for tagging your video ads is to apply the Digital Ad Ratings tag as close to the beginning of the video as possible and after initiation of the ad stream, when the ad itself begins to appear on the user’s browser, closest to the opportunity to see. To ensure video content initiates during Digital Ad Ratings measurement, tags should always be placed post buffer. Recognizing that it’s not always possible to give the Nielsen pixel priority positioning, please be aware that the placement of the tag should be discussed with the publisher/advertiser counterparty so that both sides agree on the measurement approach.<br />
<br />
In accordance with MRC requirements, Clients must append “autop” parameter to detect click to play vs auto-play to their video tags. To detect auto-refresh (page refresh), “autof” parameter must be included (not limited to video tags).<br />
<syntaxhighlight lang=javascript><br />
<img src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3&ca=cmpXXXX&cr=&pc=plcXXXX&<br />
autop=(value)&autof=(value)&r=[timestamp]" width="1" height="1" alt="" /><br />
</syntaxhighlight><br />
<br />
==== autop ====<br />
- A value of 1 will be passed when Auto-Play is detected. (e.g. autop=1)<br /><br />
- A value of 2 will be passed when Click-to-Play is detected. (e.g. autop=2)<br /><br />
- When no value or parameter is not present, impressions are labeled as Unknown Play.<br />
<br />
==== autof ====<br />
- A value of 1 will be passed when Auto-Refresh is detected. (e.g. autor=1)<br /><br />
- When no value or parameter is not present, impressions are labeled as Unknown Refresh.<br />
<br />
=== Special Note for Video Viewability Implementation: ===<br />
* Nielsen does not support any Flash based video players for viewability measurement.<br />
* The ad and tag must be in the same division (div tag) in order to track Viewability<br />
* Video:<br />
** VPAID compliant players<br />
** HTML5 Players (Flash not supported)<br />
** VPAID or mp4 creative<br />
** Video player must support VPAID and mp4<br />
<br />
=== Workflow and Tag Requirements for Nielsen Viewability with Qualified Ad Audience ===<br />
The following steps represent the tag/data flow between the publisher and Nielsen, through to final reporting.<br />
<blockquote> Please note that the assigned values for <code>CA, CI, AM, AM, PC and CR </code> in the example tags below are for illustrative purposes only to demonstrate the VW viewability state tag token. These values will need to be replaced with client specific data and/or macros specific to the ad serving situation.</blockquote><br />
<br />
# Ad creative exposed to the user<br /><br />
# Ad Server technology fires DAR tag on the publisher site<br /><br />
# Viewable state detected by Nielsen technology on publisher property; tag/signal sent to Nielsen collection system<br /><br />
# Nielsen collection system generates and executes the DAR tag with one of the following viewable states.<br />
# DAR data processing and reporting aggregates viewable impression states by campaign, placement and demographic attribution.<br />
<br />
==== Viewability Base URL &amp; Ping Paths ====<br />
<code> events.imrworldwide.com/VALUE?... </code><br />
<br />
==== Ping Path Values ====<br />
* /nmp - Measure Ping<br />
* /mp - Open Viewability Measure Ping<br />
* >/psp - Primary Standard Ping<br />
* /120sp - 120 Second Ping<br />
* /cp - Cadence Ping (used by SDK)<br />
* /fp - Final Ping<br />
* /er - Error Ping<br />
<br />
==== Nielsen DAR Tag/VPAID Query Strings ====<br />
Measure Ping<br />
<syntaxhighlight lang=html><br />
/nmp?impid=VALUE&amp;ca=VALUE&amp;ci=VALUE&amp;cr=VALUE&amp;ce=VALUE&amp;pc=VALUE&amp;am=VALUE&amp;<br />
cy=VALUE&amp;meas=VALUE&amp;ss=VALUE&amp;vp=VALUE&amp;as=VALUE&amp;al=VALUE<br />
</syntaxhighlight><br />
<br />
Primary Standard Ping<br />
<syntaxhighlight lang=html><br />
/psp?impid=VALUE&amp;vs=VALUE<br />
</syntaxhighlight><br />
<br />
120 Second Ping<br />
<syntaxhighlight lang=html><br />
/120sp?impid=VALUE&amp;vs=VALUE&amp;vts=VALUE&amp;ats=VALUE<br />
</syntaxhighlight><br />
Finish Ping<br />
<syntaxhighlight lang=html><br />
/fp?impid=VALUE&amp;vs=VALUE&amp;ss=VALUE&amp;vp=VALUE&amp;as=VALUE&amp;ar=VALUE&amp;vts=VALUE&amp;ats=VALUE<br />
</syntaxhighlight><br />
Error Ping<br />
<syntaxhighlight lang=html><br />
/er?impid=VALUE&amp;ca=VALUE&amp;ci=VALUE&amp;cr=VALUE&amp;ce=VALUE&amp;pc=VALUE&amp;am=VALUE&amp;ercd=VALUE<br />
</syntaxhighlight><br />
<br />
=== Workflow and Tag Requirements for 3rd Party Viewability ===<br />
The following steps represent the tag/data flow between publisher, Nielsen and the 3rd party viewability vendor (hereafter referred to as “vendor”), through to final reporting.<br />
<br />
<blockquote>Please note that the assigned values for CA, CI, AM, AM, PC and CR in the example tags below are for illustrative purposes only to demonstrate the VW viewability state tag token. These values will need to be replaced with client specific data and/or macros specific to the ad serving situation.</blockquote><br />
<br />
Requirements<br />
* Ad creative exposed to the user<br /><br />
* Vendor technology fires DAR tag on the publisher site<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/m?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignId]&amp;cr=[creativeId/macro]<br />
&amp;pc=[placementId/macro]&amp;r=[timestamp]<br />
</syntaxhighlight><br />
* Viewable state detected by vendor detection technology (i.e. vendor Javascript containertag) on publisher property; tag/signal sent to vendor collection system<br />
* Vendor collection system generates and executes the DAR tag with one of the following viewable state (see highlight) embedded<br />
<br />
==== onMeasureable ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignI d]&amp;cr=[creativeId/macro]&amp;pc=<br />
[amvalue]_[placementId/macro]&amp;vw=meas&amp;r=[timestamp]</syntaxhighlight><br />
<br />
==== onInViewMRC ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignId]&amp;cr=[creativeId/macro]<br />
&amp;pc=[amvalue]_[placementId/macro]&amp;vw=view&amp;r=[timestamp ]</syntaxhighlight><br />
==== onSuspicious ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignI d]&amp;cr=[creativeId/macro]<br />
&amp;pc=[amvalue]_[placementId/macro]&amp;vw=susp&amp;r=[timestamp ]</syntaxhighlight><br />
<br />
* DAR data processing and reporting aggregates viewable impression states by campaign, placement and demographic attribution.<br />
<blockquote>'''Special Note for Nielsen Viewability with Qualified Ad Audience:''' Primary owner of campaign must provide assigned Technical Account Manager (TAM) VPAID tags per site/placement in order for VAST Wrapper to be delivered back to primary owner for implementation within their respective ad server, CMS, video serving platform, etc.<br />
</blockquote><br />
<br />
<blockquote>'''Special Note for Server Side Dynamic Ad Insertion:''' In cases where Server Side Dynamic Ad Insertion (SSDAI) is present, the Nielsen tag cannot execute unless the client side video player is coded to fire impression pixels when ads play. When this happens, all of the existing specifications for tag format, time, and criteria of execution (i.e. on play of ad) previously documented must be followed.<br />
</blockquote><br />
<br />
== '''QA Testing the Tag''' ==<br />
<br />
Nielsen’s Technical Account Manager (TAM) will coordinate a plan to test fire tags in advance of the campaign go-live date.<br />
<br />
In order to test the implementation of the Nielsen tag, at least one or two (more are<br /><br />
recommended) live URLs should be provided to the TAM. If a live page cannot be made available, at staging page or offline test page should be provided. The object of this is so that the TAM can see the Nielsen call being made live, exactly as it has been implemented, to verify all of the values expected – dynamic and static - are in the tag. A spot check of a couple of placements should be sufficient unless otherwise requested. In lieu of an actual test page, we may recommend you provide a screenshot of you testing the implementation from your end, showing the Nielsen call exactly as it is being called.<br />
<br />
Additionally, we will verify that the tags delivered have begun to receive data once the campaign actually goes live and will regularly (every 7-14 days, minimally) compare the Nielsen reporting to your 3rd party or publisher reporting to ensure we are capturing all of the data for all of the placements, as expected, and that the overall gap between your reporting and the Nielsen reporting is kept to a minimum.<br />
<br />
'''Detailed steps for confirming proper tag implementation'''<br />
* Open Chrome browser and enable “Developer Tools” (shortcuts: PC, “F12” - Mac, “Command+Option+I”)<br />
<blockquote>'''NOTE''' - Other browsers or debugging tools can also be used as an alternative (ie Firefox w/HttpFox extension, Fiddler, Charles, Wireshark, etc).</blockquote><br />
* Paste test page into browser URL field<br />
* Toggle to the “Network” tab<br />
** To isolate the DAR ping you can also input “imr” into the filter box<br />
[[File:image4-dar.png|900px]]<br />
<br />
<blockquote>'''TIP''' - If DAR tag does not display try refreshing the test page</blockquote><br />
=== '''If IMAGE tags were used''' ===<br />
'''Confirm call status is 302'''<br />
This ensures a redirect has been made to our Data Enrichment Provider<br />
[[File:image5-dar.png|600px]]<br />
<br />
'''Clicking on the call and navigating to the “Headers” tab will allow you to better evaluate tag construction'''<br />
[[File:image6-dar.png|500px]]<br />
<br />
'''The “Query String” section will disclose the tag parameter'''<br />
Confirm these values are displaying as expected<br />
<blockquote>'''NOTE''' - If ad server macro tokens are used, please ensure they are expanding properly<br />
</blockquote><br />
[[File:image7-dar.png|600px]]<br />
<br />
'''Optional - Review Data Enrichment Provider call'''<br />
his can be identified by searching for “brandlift”<br />
[[File:image8-dar.png|594px]]<br />
Call status should be 200<br />
<br />
<blockquote>'''NOTE''' - campaign tag parameters are encrypted when passed to Data Enrichment Provider</blockquote><br />
[[File:image9-dar.png|600px]]<br />
<br />
=== '''If JavaScript tags were used''' ===<br />
<br />
Steps are same as the above except for the following:<br />
* Two Nielsen (“imr”) calls will be made, both with status of 200<br />
** 1st - logs the impression on Nielsen servers<br />
** 2nd - initiates the call to our Data Enrichment Provider<br />
[[File:image10-dar.png|592px]]<br />
* 3rd (Optional) call is the same as above, review Data Enrichment Provider ping. This can be identified by searching for “brandlift”<br />
[[File:image11-dar.png|580px]]<br />
<br />
== '''Managing Campaign Updates''' ==<br />
<br />
As part of the campaign monitoring process, your Nielsen TAM will stay in close contact with you throughout the campaign, including scheduling periodic check-ins to check on the campaigns (approximately every 7-14 days, but could be more often, as needed). If you have provided reporting access to the campaign via your 3rd party or have scheduled a report to be delivered on a regular (weekly) basis, this can significantly expedite the monitoring of your campaign.<br />
<br />
If you have any questions regarding setting up the reporting to be delivered, fields that will need to be included, etc., please reach out to the TAM assigned to your campaign. If not providing direct access to reporting, please schedule reporting to be delivered on a weekly basis.<br />
</blockquote><br />
<br />
== '''Frequently Asked Questions''' ==<br />
<br />
'''What is a tag?'''<br />
<br />
For our purposes, a tag is an HTML code that is placed directly on a website or inside a 3rd party ad server to track exposure to an online advertisement. Adding the Nielsen tag to the<br /><br />
banners/videos/etc. is referred to in general as ‘tagging a campaign’.<br />
<br />
'''What is served by the Nielsen tag?'''<br />
<br />
The tag call is a simple 1x1 pixel image call. There is not a survey delivered at the time of ad call so this is not intrusive to the end user and should not adversely affect site page load times. <br />
<br />
'''What should be tagged?'''<br />
<br />
As much of the campaign that can be tagged, should be, for consistency. In most cases, we generally do not tag items such as: click command/text links, default/backup ads in a 3rd party ad server, or static ‘logo’ creatives. Whenever possible, we will request that you attempt to tag all other creative types, including site-served elements.<br />
<br />
'''Is there a way to differentiate between video “auto-play” and “click-to-play” impressions?'''<br />
<br />
The Nielsen pixel does not gather this type of granularity if the events are both sharing the same ad server placement ID. If it is desirable to compare the performance between these two events, our recommendation is to traffic these as individual placements within your ad serving<br /><br />
technology.<br />
<br />
'''What is the best way to add the Nielsen tag to my campaign?'''<br />
<br />
The Nielsen pixel should be called as close to the same time as the banner ad/creative element on which you would like to track exposure. Typically, this is handled by placing our tag inside a 3rd party ad server, such as Google’s DCM or a Rich Media vendor, such as PointRoll. However, if need be, our tag can be placed directly on a site page, immediately after the ad call in the same &lt;/div&gt; as the creative file. Further instruction can be provided on the kickoff call or we can work directly with trafficking contact(s) to get the tags in place.<br />
<br />
'''Do we need to use a 3rd party ad server to use the Nielsen tag?'''<br />
<br />
The short answer is no. In a lot of cases, we have provided a tag that can be implemented directly on a site. The benefit of placing our tag inside a 3rd party ad server is that we can provide a single tag (or minimal number of tags) that contain macros to simplify the tagging process.<br />
<br />
'''Is there anything that can’t be tagged?'''<br />
<br />
We may need to review/test on a case-by-case basis, but realistically most campaign elements can be tagged. Most often, these items will need to be site served and our pixel will need to be provided to the site to implement directly. Some examples of non-standard campaign items that have been tagged before include: microsite pages, site ‘skins’, online mini-games, streaming video, pre-roll video banners.<br />
<br />
'''The site has told us that they can accept only one pixel for the site served element. Can we append your tag to the end of ours?'''<br />
<br />
If you are serving a DCM 1x1 pixel to track these elements of your campaign, we have a method for placing our tag behind this call, to be served as a redirect. For other situations, we may need to discuss further and consider other options.<br />
<br />
'''I’m using more than one Nielsen study/product on this campaign. Will I need multiple/different tags for each?'''<br />
<br />
You should not need separate tags for each study. To keep the tagging process simple, we have designed our products so that a single tag can be used for multiple online studies, however, your TAM needs to be informed of all studies before launch so that they can be enabled.<br />
<br />
'''How much detail can be tracked with the Nielsen tag?'''<br />
<br />
Typically, we do an overall read for these studies, but we can segment the data by site, placement, ad size or creative, for example. If more granular data is desired, this should be discussed ahead of the campaign launch and planned for at the time of tag creation. ''We cannot segment the data if we have not tagged for it'' -- multiple tags will need to be created and implemented properly. Note that this can often be a time consuming process for the client trafficker and additional time should be allotted if this is needed. Lastly, keep in mind that exposure sample size may be a factor for segmenting the data at a more granular level.<br />
<br />
'''Why is it recommended to implement a timestamp or random number on the tag?''' This value will ensure that the tag call will not be cached on a user’s browser. It’s not absolutely necessary to implement for the tag to work, but without it you may see a larger gap between the impressions ran and what Nielsen captures. It is recommended to minimize this gap.<br />
<br />
'''For campaigns involving Facebook, what can’t be tagged on their site?'''<br />
<br />
Fan/Like pages are not allowed to be tagged, per Facebook. Additionally, Marketplace slots are not allowed to be tagged as these are user generated ads.<br />
<br />
'''What if it is not possible to provide a test or staging page before launch?'''<br />
<br />
While not ideal, we can view raw impression numbers on the day of the launch as well as review a live example if a URL is provided. Another option would to test from the client/site side and provide a screenshot of the Nielsen call being made using a proxy tool (HTTPWatch, Fiddler, Charles, etc.) – prior to launch. The aim either way is to minimize missing impressions for your campaign, so it is in your best interest to provide for this testing if you can.<br />
<br />
'''What is considered to be an acceptable gap in reporting?'''<br />
<br />
In a perfect world, we’d like to see no gap in the numbers. We realize this is simply not possible – it is a factor of the Internet and having different counting methodologies, so we will aim for the lowest overall gap we can. Even with everything trafficked correctly; it is not uncommon to see gaps in the range of 5 to 10%, so we shoot for this range (if it’s lower than that, that’s great). If it’s greater than 10%, it usually indicates that there was something that was missed from being tagged or there’s an additional issue that requires further attention. When issues arise, we make all attempts to highlight and communicate the issue seen, to minimize the overall impact to the study, but are reliant on the client to ensure the issue is fixed. In a campaign where there are issues such as this, we try to keep the gap under 20% and will document any issues found. What are the capabilities for tagging video and video based ads?<br />
<br />
Our tag is not a specific limitation as it is one of the simplest things that can be served – a 1x1 image. That being said, much of the video implementation limitations are often dictated by the video vendors themselves. Where you can add our tag is dependent on the capabilities of these vendors. Some have the ability to place the tag in multiple locations in the video (i.e. beginning, middle, end – multiple tags will be needed to separate these out) and some simply place the pixel directly on the webpage, next to video being served. Further discussion may need to happen with the vendor, Nielsen and the client to determine the optimum implementation that meets the client's needs.<br />
</blockquote></div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DAR_Tag_Implementation_Guide&diff=5661DAR Tag Implementation Guide2022-03-01T17:11:38Z<p>LaMarHolmes: /* Unified ID */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
<br />
== Introduction ==<br />
<br />
Nielsen Digital Ad Ratings is a measurement platform for online advertising campaigns. The platform provides a clear view of the true audience of a campaign, including '''Reach''', '''Frequency''', and '''GRP''' statistics by audience demographic group.<br />
<br />
The key innovation of the platform is the inclusion of demographic data from leading web publishers to attach actual user demographics to ad impressions.<br />
<br />
The diagram below summarizes how the Nielsen tag measures the ad campaign:<br />
# Advertiser places ads on one or more websites<br />
#Website displays ad to a user<br />
#Nielsen tag counts impressions and controls redirect to the Data Enrichment Provider<br />
[[File:dar-image2.png|900px]]<br />
<br />
<br />
=== Support for Other Nielsen Ad Effectiveness Products ===<br />
<br />
The tag used for Nielsen Digital Ad Ratings is compatible for all Nielsen Ad Effectiveness products, including (but not limited to) Brand Effect Extended View, Response Effect, and Sales Effect.<br />
<br />
=== User Experience ===<br />
<br />
The tags described in this document are used only to measure audience exposure to advertisements; they do not launch a survey, and have no impact on the user experience. Typical response time for the tag is on par with industry standards and because the code executed is simple and fires after the ad loads, they are transparent to the user.<br />
<br />
For further information on survey-based products, or any other products, please contact your Client Services Manager.<br />
__TOC__<br />
<br />
== Available Tag Versions ==<br />
<br />
The Nielsen Digital Ad Ratings system offers 2 basic types of ad tags<br />
<br />
* '''IMAGE (1X1) Pixel'''<br />
This is the simplest version of the tag, generally for use by clients who cannot accept JavaScript format tags or have limited options for implementation. Itincludes encryption, but does not utilize referrer masking.<br />
<br />
* '''JavaScript Tag'''<br />
This is a more complex tag which includes encryption and masking of referrer site via a script call. This Tag may also be used to measure Viewability metrics.<br />
There may be additional functionality offered by this format in future releases as well.<br />
* '''Ad Networks''' This tag includes additional functionality to scrape the URL of the hosting website if associated to an ad network within the Nielsen system. Keep in mind URLs captured will only be used for “site adjustment factors” and not be included in any reporting<br />
<br />
<blockquote>'''NOTE''' - Both tag types support macros and are available in secure and non-secure formats. Please reach out to your Nielsen Technical Account Manager for additional information.</blockquote><br />
<br />
While the IMAGE pixels are easiest to implement, the JavaScript versions are recommended because they provide the highest level of confidentiality by masking the source of the ad from being viewable by Data Providers. Some situations may not afford use of JavaScript and in those cases, the pixel version will be recommended. Note that in many cases the referrer is cast as the ad server due to the nature of being served inside iframes, so the “masking” here is extraneous.<br />
<br />
=== Tag Examples ===<br />
<br />
<br><br />
'''IMAGE Pixel Tag''' (Static example)<br />
<syntaxhighlight lang="javascript"><br />
<img src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3&ca=cmpXXXX&cr=&pc=plcXXXX&r=[timestamp]"<br />
width="1" height="1" alt=""/><br />
</syntaxhighlight><br />
<br />
'''IMAGE Pixel Tag''' (Macro example)<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"><br />
</script><br />
</syntaxhighlight><br />
<br />
'''JavaScript Tag''' (Static example)<br />
<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3mr=1&ty=js&ca=cmpXXXX&cr=&pc=plcXXXX&r=[timestamp]"<br />
></script><br />
</syntaxhighlight><br />
<br />
'''JavaScript Tag''' (Macro example)<br />
<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"></<br />
script><br />
</syntaxhighlight><br />
<br><br />
<br />
The Nielsen Digital Ad Ratings system also features the ability to record Viewability information such as: How long an Ad has been visible on the screen, and what portion on the Ad. This is an additional feature that can be purchased from your Nielsen Client Services Representative.<br />
<br />
Viewability for display ads can ONLY be offered through the JavaScript tag. If you select this service, the following is an example of the tag that will be provided to you by the Nielsen Digital Implementation Team:<br />
<br />
'''JavaScript with Viewability for display ads:'''<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"></<br />
script><br />
</syntaxhighlight><br />
<br />
<blockquote>The above tag is just examples and should not be placed in any live site or ad server. You will be provided with tags specifically designed for your media plan/campaign or be able to download tags after creation in CMI (Campaign Management Interface)</blockquote><br />
<br />
== Standard DAR Tag ==<br />
The DAR tag is available as a 1x1 pixel. The following pixel/tag parameters must be specified for all DAR tags, 1x1, regardless of implementation type: browser, mobile browser, mobile app or connected device.<br />
<br />
{| class="wikitable" <br />
|-<br />
! Tag Parameter<br />
! Description<br />
|-<br />
| CI<br />
| Client ID: the ID that is associated with the DAR account that processed tag data is associated with. Will always be hardcoded to a Nielsen generated value that comes from the Nielsen campaign management system<br />
|- style="background-color:#eff8ef;"<br />
| AM<br />
| Ad Server: an ad server participating on the campaign media-plan. This is an internal Nielsen generated value when the ad server is indicated on the campaign during setup<br />
|-<br />
| CA<br />
| Campaign Id: this is the ID associated with your DAR campaign. Unless you are creating and managing the Nielsen campaign via the DAR Tag API, then this parameter value will always be generated from the Nielsen campaign management system. Note: often maps to a media-plan I/O Id<br />
|- style="background-color:#eff8ef;"<br />
| CR<br />
| Creative Id: DAR does not currently report at the creative level; can be hard coded ad server id or associated with a macro expansion<br />
|-<br />
| PC<br />
| Placement Id: can be generated by the ad server via macro expansion or generated by the Nielsen campaign management system. Note: often maps to one of Ad Unit Id, Line Item Id or Video Ad Id<br />
|- style="background-color:#eff8ef;"<br />
| CE<br />
| Site Id: the Id that identifies a publisher site that the placement needs to be mapped to. Maps into the Nielsen MarketView database. Note: can be hardcoded to a pre-registered ad server site id in the Nielsen system or a macro expansion where more than one pre-existing site ids have been made known to Nielsen<br />
|-<br />
| R<br />
| Cachebuster (web): timestamp / random number. Generated by ad server<br />
|- style="background-color:#eff8ef;"<br />
| AT<br />
| Fixed value: “view”<br />
|-<br />
| RT<br />
| Fixed value: “banner”<br />
|- style="background-color:#eff8ef;"<br />
| ST<br />
| Fixed value: “image”<br />
|}<br />
<blockquote> Do not URL encode the values</blockquote><br />
<br />
== Additional Parameters ==<br />
In this section we describe the additional parameters that the DAR tag can support, specifically Hashed Email, UID2 values, along with Page URL and Bundle Identifier if available. Please work with your Nielsen Technical Account Manager on deciding which of the following parameters to append to the standard DAR tag. <br />
<br />
'''Web Browser DAR tag (cookie based persons identification)'''<br />
<br />
[https://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=nlsn_plc0001&ce=000&r=34245454 https://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=<siteid>&r=<timestamp>]<br />
<br />
'''Web Browser PLUS tag'''<br />
<br />
[http://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=554554_plc0001&ce=0000 http://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=0000]&hem_sha256=<value>&uid2=<value>&uid_token=<value>&si=<value>c68=bndlid,com.tam.nielsen.com<br />
<br />
=== HEM Support (Hashed Email) ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"| Hashed Email <br />
| User’s email address that has been run through a hashing algorithm (e.g. SHA256, MD5, SHA1) </br> to create a unique string. If a client is unable to determine hashing type, they should pass using &hem_unknown parameter.<br />
|style="width: 20%"|<code>&hem_unknown</br>&hem_sha256</br>&hem_md5</br>&hem_sha1</code><br />
|}<br />
<br />
<blockquote>Please use the parameter that matches your hashing algorithm.<br> For example, if you are using sha256 to encode the email address, then use <code>hem_sha256={encrypted_value_here}</code><br />
</blockquote><br />
Example:<br />
<syntaxhighlight lang="javascript"><br />
hem_sha256=tMmiiTI7IaAcPpQPFQ65uMVCWH8av9jw4cwf/F5HVRQ=<br />
</syntaxhighlight><br />
<br />
=== Unified ID ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"| Unified ID 2.0<br />
| An identifier based on a user’s verifiable PII (e.g. hashed email). UID2.0 was initially created by The Trade Desk (TTD)</br> and is now managed by Prebid. For more information on UID2.0 : https://github.com/UnifiedID2/uid2docs<br />
| &uid2<br />
|}<br />
<br />
Example:<br />
<syntaxhighlight lang="javascript"><br />
uid2=MTKVpUAzwYAPnHrtfE0wlINOMzhU7UUEjjVdCdRu63k=<br />
uid_token=AgAAAAPFR0zA5ogv/yaAPiUsAdZPsfqS8QlDSGxAB+rr8yekFs3AjLYVk5qqqiyV2XHbSuwzHmxSlLeQeKQI1mp015jsNnpX5/xGgXldcgVz+gFnyh3T8/3agMwRmyrhCxG4oH2C7<br />
fc48AQk2eotE7FW0ZDEYM8fD9ZxDaxFUC/OV3OuZA&<br />
</syntaxhighlight><br />
<br />
=== Page and Bundle ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"|Page URL<br />
| style="width: 65%"| Canonical URL of the content where the Ad creative is served. (e.g. https://example.com/news/tech/article.html) The parameter value has to be encoded with JavaScript’s encodeURIComponent() method or equivalent. <br />Example: si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
| &si<br />
|-<br />
| App Bundle ID<br />
| The app’s unique bundle ID (e.g. com.example.myapp). The ID can be used to look up the App in Apple’s App Store</br> or the Google Play Store. References:https://developer.android.com/studio/build/application-idhttps://developer.apple.com/documentation/appstoreconnectapi/bundle_ids<br />
| &c68=bndlid,<br />
|}<br />
<br />
Example:<br />
<syntaxhighlight><br />
si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
c68=bndlid,com.tam.nielsen.com<br />
</syntaxhighlight><br />
<br />
== Supported Creative Types ==<br />
<br />
For consistency, Nielsen recommends tagging as much of the campaign creative types as possible, including site-served elements. '''Note:''' Nielsen may need to review/test on a case-by-case basis.<br />
<br />
Nielsen Digital Ad Ratings supports banner ads, rich media and video units that are capable of being tagged with a 3rd party tracking pixel.<br />
<blockquote>Some examples of non-standard campaign items that may be tagged include:<br />
* microsite pages<br />
* site “skins’”<br />
* online mini-games<br />
* streaming video<br />
* pre-roll video banners<br />
</blockquote><br />
Most often, these items will need to be site served and our pixel will need to be provided to the site to implement directly.<br />
<blockquote>The following are items not tagged:<br />
* click command/text links<br />
* default/backup ads in a 3rd party ad server<br />
* static ‘logo’ creatives<br />
</blockquote><br />
<br />
Digital Ad Ratings Viewability Solution: All standard ad units listed under [http://www.iab.net/displayguidelines Universal Ad Package (UAP)] on are supported for Viewability.<br />
<br />
Placements and sites that cannot support JavaScript cannot support Viewability.<br />
<br />
'''‘Best Practices’ for Video Tags:''' Nielsen recommends all video tags be deployed as close to the beginning of the video stream as possible (post buffer).<br />
Placements delivering to Flash creative should have our tag implemented within the Flash code.<br />
<br />
== How the Tag Works ==<br />
<br />
The following describes the masked javascript version of the tag. <br><br />
For the non-masked pixel version of the tag, steps 5-8 would be collapsed to just 2 steps.<br />
<br />
[[File:image3-dar.png|right|500px]]<br />
# End-user uses her web browser to visit a website that contains an ad creative being measured by Nielsen.<br />
# Website sends web page back to end-user. (Web page contains HTML describing web content & ads)<br />
# End-user’s web browser requests the ad creative from Ad Server<br />
# Ad Server sends an iframe ad creative back to the end-user which contains the Nielsen measurement tag<br />
# End-user’s web browser makes a request to the Nielsen servers.<br />
## The tag’s HTTP request contains a campaign ID and placement, which is collected by Nielsen<br />
## The Nielsen system checks the user’s machine for an opt-out cookie – if one exists the process ends here<br />
## The Nielsen system checks to see if the campaign value in the tag was selected for Viewability. If so it downloads the Integral Ad Science tag to the end-user’s browser.<br />
# Nielsen server sends JavaScript code back to end-user’s web browser, including a 1x1 pixel.<br />
# End-user’s web browser executes JavaScript code and makes an iframe request to Nielsen server to enable the “referrer masking redirect”<br />
# Nielsen server sends an HTML message to the end-user’s web browser.<br />
# End-user’s web browser executes HTML and requests a 1x1 pixel from the Data Provider using Nielsen server information as the HTTP referrer – thus masking the Website’s information<br />
## The campaign ID and placement ID are passed through to Data Provider in an encrypted format<br />
# If Viewability is enabled the JavaScript will download a Javascript tag that calls the viewability vendor (either Nielsen or 3rd Party) to begin tracking inview metrics.<br />
# Data Provider responds with a 1x1 pixel. End process.<br />
<br />
== Share Your Delivered Impressions ==<br />
<br />
'''Why the Media Plan is Needed'''<br />
<br />
Knowing the delivered impressions also helps Nielsen run automated QA checks, for example triggering alerts when data does not appear for a placement on an expected date. This ensures overall quality, and reduces errors in the tagging process.<br />
<br />
It is the responsibility of the client to send Nielsen an impression delivery report, generally known as the “ad server report.” Nielsen can provide the client with a template with the inputs required to complete the quality checks. If the client does not send these reports, Nielsen will not be able to complete the quality checks. Below are instructions on how to send these reports to Nielsen.<br />
<br />
'''How to Share Your Delivered impressions'''<br />
<br />
Set up an automated daily report from your ad server containing Site Name, Site ID, Placement Name, Placement ID, and data date.<br />
<br />
A secondary method to share your media plan information is to grant Nielsen “Reporting access” to your campaign in the designated ad server (such as DCM). To do this, simply grant the login [http://mailto:clientreporting@nielsen.com clientreporting@nielsen.com] access. In doing so Nielsen can directly access your media plan information, which enables us to check for updates, and reconcile any<br /><br />
discrepancies.<br />
<br />
<blockquote>Please note that Nielsen is currently in discussions with several leading Ad Servers regarding direct integration between Nielsen and the ad server platforms. Once completed this could someday enable Nielsen to retrieve Media Plans on a completed automated basis.<br />
</blockquote><br />
<br />
== Apply the Tag ==<br />
=== Tag Generation ===<br />
<br />
Your Nielsen representative will walk you through the Campaign Management Interface so that you can download tags at will at any point in the campaign.<br />
<br />
Nielsen supports macro-based tag generation for several major ad servers. Nielsen’s Technical Account Manager (TAM) can assist you in leveraging macro-based tags.<br />
<br />
=== Tag Application ===<br />
<br />
Apply the tag according to the 3rd party tracking pixel specifications of your ad server. If additional guidance is needed, please consult with the Technical Account Manager (TAM) for more specific instructions or recommendations, if available.<br />
<br />
== Special Note for Video Tags ==<br />
Nielsen’s recommended “Best Practice” for tagging your video ads is to apply the Digital Ad Ratings tag as close to the beginning of the video as possible and after initiation of the ad stream, when the ad itself begins to appear on the user’s browser, closest to the opportunity to see. To ensure video content initiates during Digital Ad Ratings measurement, tags should always be placed post buffer. Recognizing that it’s not always possible to give the Nielsen pixel priority positioning, please be aware that the placement of the tag should be discussed with the publisher/advertiser counterparty so that both sides agree on the measurement approach.<br />
<br />
In accordance with MRC requirements, Clients must append “autop” parameter to detect click to play vs auto-play to their video tags. To detect auto-refresh (page refresh), “autof” parameter must be included (not limited to video tags).<br />
<syntaxhighlight lang=javascript><br />
<img src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3&ca=cmpXXXX&cr=&pc=plcXXXX&<br />
autop=(value)&autof=(value)&r=[timestamp]" width="1" height="1" alt="" /><br />
</syntaxhighlight><br />
<br />
==== autop ====<br />
- A value of 1 will be passed when Auto-Play is detected. (e.g. autop=1)<br /><br />
- A value of 2 will be passed when Click-to-Play is detected. (e.g. autop=2)<br /><br />
- When no value or parameter is not present, impressions are labeled as Unknown Play.<br />
<br />
==== autof ====<br />
- A value of 1 will be passed when Auto-Refresh is detected. (e.g. autor=1)<br /><br />
- When no value or parameter is not present, impressions are labeled as Unknown Refresh.<br />
<br />
=== Special Note for Video Viewability Implementation: ===<br />
* Nielsen does not support any Flash based video players for viewability measurement.<br />
* The ad and tag must be in the same division (div tag) in order to track Viewability<br />
* Video:<br />
** VPAID compliant players<br />
** HTML5 Players (Flash not supported)<br />
** VPAID or mp4 creative<br />
** Video player must support VPAID and mp4<br />
<br />
=== Workflow and Tag Requirements for Nielsen Viewability with Qualified Ad Audience ===<br />
The following steps represent the tag/data flow between the publisher and Nielsen, through to final reporting.<br />
<blockquote> Please note that the assigned values for <code>CA, CI, AM, AM, PC and CR </code> in the example tags below are for illustrative purposes only to demonstrate the VW viewability state tag token. These values will need to be replaced with client specific data and/or macros specific to the ad serving situation.</blockquote><br />
<br />
# Ad creative exposed to the user<br /><br />
# Ad Server technology fires DAR tag on the publisher site<br /><br />
# Viewable state detected by Nielsen technology on publisher property; tag/signal sent to Nielsen collection system<br /><br />
# Nielsen collection system generates and executes the DAR tag with one of the following viewable states.<br />
# DAR data processing and reporting aggregates viewable impression states by campaign, placement and demographic attribution.<br />
<br />
==== Viewability Base URL &amp; Ping Paths ====<br />
<code> events.imrworldwide.com/VALUE?... </code><br />
<br />
==== Ping Path Values ====<br />
* /nmp - Measure Ping<br />
* /mp - Open Viewability Measure Ping<br />
* >/psp - Primary Standard Ping<br />
* /120sp - 120 Second Ping<br />
* /cp - Cadence Ping (used by SDK)<br />
* /fp - Final Ping<br />
* /er - Error Ping<br />
<br />
==== Nielsen DAR Tag/VPAID Query Strings ====<br />
Measure Ping<br />
<syntaxhighlight lang=html><br />
/nmp?impid=VALUE&amp;ca=VALUE&amp;ci=VALUE&amp;cr=VALUE&amp;ce=VALUE&amp;pc=VALUE&amp;am=VALUE&amp;<br />
cy=VALUE&amp;meas=VALUE&amp;ss=VALUE&amp;vp=VALUE&amp;as=VALUE&amp;al=VALUE<br />
</syntaxhighlight><br />
<br />
Primary Standard Ping<br />
<syntaxhighlight lang=html><br />
/psp?impid=VALUE&amp;vs=VALUE<br />
</syntaxhighlight><br />
<br />
120 Second Ping<br />
<syntaxhighlight lang=html><br />
/120sp?impid=VALUE&amp;vs=VALUE&amp;vts=VALUE&amp;ats=VALUE<br />
</syntaxhighlight><br />
Finish Ping<br />
<syntaxhighlight lang=html><br />
/fp?impid=VALUE&amp;vs=VALUE&amp;ss=VALUE&amp;vp=VALUE&amp;as=VALUE&amp;ar=VALUE&amp;vts=VALUE&amp;ats=VALUE<br />
</syntaxhighlight><br />
Error Ping<br />
<syntaxhighlight lang=html><br />
/er?impid=VALUE&amp;ca=VALUE&amp;ci=VALUE&amp;cr=VALUE&amp;ce=VALUE&amp;pc=VALUE&amp;am=VALUE&amp;ercd=VALUE<br />
</syntaxhighlight><br />
<br />
=== Workflow and Tag Requirements for 3rd Party Viewability ===<br />
The following steps represent the tag/data flow between publisher, Nielsen and the 3rd party viewability vendor (hereafter referred to as “vendor”), through to final reporting.<br />
<br />
<blockquote>Please note that the assigned values for CA, CI, AM, AM, PC and CR in the example tags below are for illustrative purposes only to demonstrate the VW viewability state tag token. These values will need to be replaced with client specific data and/or macros specific to the ad serving situation.</blockquote><br />
<br />
Requirements<br />
* Ad creative exposed to the user<br /><br />
* Vendor technology fires DAR tag on the publisher site<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/m?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignId]&amp;cr=[creativeId/macro]<br />
&amp;pc=[placementId/macro]&amp;r=[timestamp]<br />
</syntaxhighlight><br />
* Viewable state detected by vendor detection technology (i.e. vendor Javascript containertag) on publisher property; tag/signal sent to vendor collection system<br />
* Vendor collection system generates and executes the DAR tag with one of the following viewable state (see highlight) embedded<br />
<br />
==== onMeasureable ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignI d]&amp;cr=[creativeId/macro]&amp;pc=<br />
[amvalue]_[placementId/macro]&amp;vw=meas&amp;r=[timestamp]</syntaxhighlight><br />
<br />
==== onInViewMRC ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignId]&amp;cr=[creativeId/macro]<br />
&amp;pc=[amvalue]_[placementId/macro]&amp;vw=view&amp;r=[timestamp ]</syntaxhighlight><br />
==== onSuspicious ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignI d]&amp;cr=[creativeId/macro]<br />
&amp;pc=[amvalue]_[placementId/macro]&amp;vw=susp&amp;r=[timestamp ]</syntaxhighlight><br />
<br />
* DAR data processing and reporting aggregates viewable impression states by campaign, placement and demographic attribution.<br />
<blockquote>'''Special Note for Nielsen Viewability with Qualified Ad Audience:''' Primary owner of campaign must provide assigned Technical Account Manager (TAM) VPAID tags per site/placement in order for VAST Wrapper to be delivered back to primary owner for implementation within their respective ad server, CMS, video serving platform, etc.<br />
</blockquote><br />
<br />
<blockquote>'''Special Note for Server Side Dynamic Ad Insertion:''' In cases where Server Side Dynamic Ad Insertion (SSDAI) is present, the Nielsen tag cannot execute unless the client side video player is coded to fire impression pixels when ads play. When this happens, all of the existing specifications for tag format, time, and criteria of execution (i.e. on play of ad) previously documented must be followed.<br />
</blockquote><br />
<br />
== '''QA Testing the Tag''' ==<br />
<br />
Nielsen’s Technical Account Manager (TAM) will coordinate a plan to test fire tags in advance of the campaign go-live date.<br />
<br />
In order to test the implementation of the Nielsen tag, at least one or two (more are<br /><br />
recommended) live URLs should be provided to the TAM. If a live page cannot be made available, at staging page or offline test page should be provided. The object of this is so that the TAM can see the Nielsen call being made live, exactly as it has been implemented, to verify all of the values expected – dynamic and static - are in the tag. A spot check of a couple of placements should be sufficient unless otherwise requested. In lieu of an actual test page, we may recommend you provide a screenshot of you testing the implementation from your end, showing the Nielsen call exactly as it is being called.<br />
<br />
Additionally, we will verify that the tags delivered have begun to receive data once the campaign actually goes live and will regularly (every 7-14 days, minimally) compare the Nielsen reporting to your 3rd party or publisher reporting to ensure we are capturing all of the data for all of the placements, as expected, and that the overall gap between your reporting and the Nielsen reporting is kept to a minimum.<br />
<br />
'''Detailed steps for confirming proper tag implementation'''<br />
* Open Chrome browser and enable “Developer Tools” (shortcuts: PC, “F12” - Mac, “Command+Option+I”)<br />
<blockquote>'''NOTE''' - Other browsers or debugging tools can also be used as an alternative (ie Firefox w/HttpFox extension, Fiddler, Charles, Wireshark, etc).</blockquote><br />
* Paste test page into browser URL field<br />
* Toggle to the “Network” tab<br />
** To isolate the DAR ping you can also input “imr” into the filter box<br />
[[File:image4-dar.png|900px]]<br />
<br />
<blockquote>'''TIP''' - If DAR tag does not display try refreshing the test page</blockquote><br />
=== '''If IMAGE tags were used''' ===<br />
'''Confirm call status is 302'''<br />
This ensures a redirect has been made to our Data Enrichment Provider<br />
[[File:image5-dar.png|600px]]<br />
<br />
'''Clicking on the call and navigating to the “Headers” tab will allow you to better evaluate tag construction'''<br />
[[File:image6-dar.png|500px]]<br />
<br />
'''The “Query String” section will disclose the tag parameter'''<br />
Confirm these values are displaying as expected<br />
<blockquote>'''NOTE''' - If ad server macro tokens are used, please ensure they are expanding properly<br />
</blockquote><br />
[[File:image7-dar.png|600px]]<br />
<br />
'''Optional - Review Data Enrichment Provider call'''<br />
his can be identified by searching for “brandlift”<br />
[[File:image8-dar.png|594px]]<br />
Call status should be 200<br />
<br />
<blockquote>'''NOTE''' - campaign tag parameters are encrypted when passed to Data Enrichment Provider</blockquote><br />
[[File:image9-dar.png|600px]]<br />
<br />
=== '''If JavaScript tags were used''' ===<br />
<br />
Steps are same as the above except for the following:<br />
* Two Nielsen (“imr”) calls will be made, both with status of 200<br />
** 1st - logs the impression on Nielsen servers<br />
** 2nd - initiates the call to our Data Enrichment Provider<br />
[[File:image10-dar.png|592px]]<br />
* 3rd (Optional) call is the same as above, review Data Enrichment Provider ping. This can be identified by searching for “brandlift”<br />
[[File:image11-dar.png|580px]]<br />
<br />
== '''Managing Campaign Updates''' ==<br />
<br />
As part of the campaign monitoring process, your Nielsen TAM will stay in close contact with you throughout the campaign, including scheduling periodic check-ins to check on the campaigns (approximately every 7-14 days, but could be more often, as needed). If you have provided reporting access to the campaign via your 3rd party or have scheduled a report to be delivered on a regular (weekly) basis, this can significantly expedite the monitoring of your campaign.<br />
<br />
If you have any questions regarding setting up the reporting to be delivered, fields that will need to be included, etc., please reach out to the TAM assigned to your campaign. If not providing direct access to reporting, please schedule reporting to be delivered on a weekly basis.<br />
</blockquote><br />
<br />
== '''Frequently Asked Questions''' ==<br />
<br />
'''What is a tag?'''<br />
<br />
For our purposes, a tag is an HTML code that is placed directly on a website or inside a 3rd party ad server to track exposure to an online advertisement. Adding the Nielsen tag to the<br /><br />
banners/videos/etc. is referred to in general as ‘tagging a campaign’.<br />
<br />
'''What is served by the Nielsen tag?'''<br />
<br />
The tag call is a simple 1x1 pixel image call. There is not a survey delivered at the time of ad call so this is not intrusive to the end user and should not adversely affect site page load times. <br />
<br />
'''What should be tagged?'''<br />
<br />
As much of the campaign that can be tagged, should be, for consistency. In most cases, we generally do not tag items such as: click command/text links, default/backup ads in a 3rd party ad server, or static ‘logo’ creatives. Whenever possible, we will request that you attempt to tag all other creative types, including site-served elements.<br />
<br />
'''Is there a way to differentiate between video “auto-play” and “click-to-play” impressions?'''<br />
<br />
The Nielsen pixel does not gather this type of granularity if the events are both sharing the same ad server placement ID. If it is desirable to compare the performance between these two events, our recommendation is to traffic these as individual placements within your ad serving<br /><br />
technology.<br />
<br />
'''What is the best way to add the Nielsen tag to my campaign?'''<br />
<br />
The Nielsen pixel should be called as close to the same time as the banner ad/creative element on which you would like to track exposure. Typically, this is handled by placing our tag inside a 3rd party ad server, such as Google’s DCM or a Rich Media vendor, such as PointRoll. However, if need be, our tag can be placed directly on a site page, immediately after the ad call in the same &lt;/div&gt; as the creative file. Further instruction can be provided on the kickoff call or we can work directly with trafficking contact(s) to get the tags in place.<br />
<br />
'''Do we need to use a 3rd party ad server to use the Nielsen tag?'''<br />
<br />
The short answer is no. In a lot of cases, we have provided a tag that can be implemented directly on a site. The benefit of placing our tag inside a 3rd party ad server is that we can provide a single tag (or minimal number of tags) that contain macros to simplify the tagging process.<br />
<br />
'''Is there anything that can’t be tagged?'''<br />
<br />
We may need to review/test on a case-by-case basis, but realistically most campaign elements can be tagged. Most often, these items will need to be site served and our pixel will need to be provided to the site to implement directly. Some examples of non-standard campaign items that have been tagged before include: microsite pages, site ‘skins’, online mini-games, streaming video, pre-roll video banners.<br />
<br />
'''The site has told us that they can accept only one pixel for the site served element. Can we append your tag to the end of ours?'''<br />
<br />
If you are serving a DCM 1x1 pixel to track these elements of your campaign, we have a method for placing our tag behind this call, to be served as a redirect. For other situations, we may need to discuss further and consider other options.<br />
<br />
'''I’m using more than one Nielsen study/product on this campaign. Will I need multiple/different tags for each?'''<br />
<br />
You should not need separate tags for each study. To keep the tagging process simple, we have designed our products so that a single tag can be used for multiple online studies, however, your TAM needs to be informed of all studies before launch so that they can be enabled.<br />
<br />
'''How much detail can be tracked with the Nielsen tag?'''<br />
<br />
Typically, we do an overall read for these studies, but we can segment the data by site, placement, ad size or creative, for example. If more granular data is desired, this should be discussed ahead of the campaign launch and planned for at the time of tag creation. ''We cannot segment the data if we have not tagged for it'' -- multiple tags will need to be created and implemented properly. Note that this can often be a time consuming process for the client trafficker and additional time should be allotted if this is needed. Lastly, keep in mind that exposure sample size may be a factor for segmenting the data at a more granular level.<br />
<br />
'''Why is it recommended to implement a timestamp or random number on the tag?''' This value will ensure that the tag call will not be cached on a user’s browser. It’s not absolutely necessary to implement for the tag to work, but without it you may see a larger gap between the impressions ran and what Nielsen captures. It is recommended to minimize this gap.<br />
<br />
'''For campaigns involving Facebook, what can’t be tagged on their site?'''<br />
<br />
Fan/Like pages are not allowed to be tagged, per Facebook. Additionally, Marketplace slots are not allowed to be tagged as these are user generated ads.<br />
<br />
'''What if it is not possible to provide a test or staging page before launch?'''<br />
<br />
While not ideal, we can view raw impression numbers on the day of the launch as well as review a live example if a URL is provided. Another option would to test from the client/site side and provide a screenshot of the Nielsen call being made using a proxy tool (HTTPWatch, Fiddler, Charles, etc.) – prior to launch. The aim either way is to minimize missing impressions for your campaign, so it is in your best interest to provide for this testing if you can.<br />
<br />
'''What is considered to be an acceptable gap in reporting?'''<br />
<br />
In a perfect world, we’d like to see no gap in the numbers. We realize this is simply not possible – it is a factor of the Internet and having different counting methodologies, so we will aim for the lowest overall gap we can. Even with everything trafficked correctly; it is not uncommon to see gaps in the range of 5 to 10%, so we shoot for this range (if it’s lower than that, that’s great). If it’s greater than 10%, it usually indicates that there was something that was missed from being tagged or there’s an additional issue that requires further attention. When issues arise, we make all attempts to highlight and communicate the issue seen, to minimize the overall impact to the study, but are reliant on the client to ensure the issue is fixed. In a campaign where there are issues such as this, we try to keep the gap under 20% and will document any issues found. What are the capabilities for tagging video and video based ads?<br />
<br />
Our tag is not a specific limitation as it is one of the simplest things that can be served – a 1x1 image. That being said, much of the video implementation limitations are often dictated by the video vendors themselves. Where you can add our tag is dependent on the capabilities of these vendors. Some have the ability to place the tag in multiple locations in the video (i.e. beginning, middle, end – multiple tags will be needed to separate these out) and some simply place the pixel directly on the webpage, next to video being served. Further discussion may need to happen with the vendor, Nielsen and the client to determine the optimum implementation that meets the client's needs.<br />
</blockquote></div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DAR_Tag_Implementation_Guide&diff=5636DAR Tag Implementation Guide2022-02-10T17:38:52Z<p>LaMarHolmes: /* HEM Support (Hashed Email) */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
<br />
== Introduction ==<br />
<br />
Nielsen Digital Ad Ratings is a measurement platform for online advertising campaigns. The platform provides a clear view of the true audience of a campaign, including '''Reach''', '''Frequency''', and '''GRP''' statistics by audience demographic group.<br />
<br />
The key innovation of the platform is the inclusion of demographic data from leading web publishers to attach actual user demographics to ad impressions.<br />
<br />
The diagram below summarizes how the Nielsen tag measures the ad campaign:<br />
# Advertiser places ads on one or more websites<br />
#Website displays ad to a user<br />
#Nielsen tag counts impressions and controls redirect to the Data Enrichment Provider<br />
[[File:dar-image2.png|900px]]<br />
<br />
<br />
=== Support for Other Nielsen Ad Effectiveness Products ===<br />
<br />
The tag used for Nielsen Digital Ad Ratings is compatible for all Nielsen Ad Effectiveness products, including (but not limited to) Brand Effect Extended View, Response Effect, and Sales Effect.<br />
<br />
=== User Experience ===<br />
<br />
The tags described in this document are used only to measure audience exposure to advertisements; they do not launch a survey, and have no impact on the user experience. Typical response time for the tag is on par with industry standards and because the code executed is simple and fires after the ad loads, they are transparent to the user.<br />
<br />
For further information on survey-based products, or any other products, please contact your Client Services Manager.<br />
__TOC__<br />
<br />
== Available Tag Versions ==<br />
<br />
The Nielsen Digital Ad Ratings system offers 2 basic types of ad tags<br />
<br />
* '''IMAGE (1X1) Pixel'''<br />
This is the simplest version of the tag, generally for use by clients who cannot accept JavaScript format tags or have limited options for implementation. Itincludes encryption, but does not utilize referrer masking.<br />
<br />
* '''JavaScript Tag'''<br />
This is a more complex tag which includes encryption and masking of referrer site via a script call. This Tag may also be used to measure Viewability metrics.<br />
There may be additional functionality offered by this format in future releases as well.<br />
* '''Ad Networks''' This tag includes additional functionality to scrape the URL of the hosting website if associated to an ad network within the Nielsen system. Keep in mind URLs captured will only be used for “site adjustment factors” and not be included in any reporting<br />
<br />
<blockquote>'''NOTE''' - Both tag types support macros and are available in secure and non-secure formats. Please reach out to your Nielsen Technical Account Manager for additional information.</blockquote><br />
<br />
While the IMAGE pixels are easiest to implement, the JavaScript versions are recommended because they provide the highest level of confidentiality by masking the source of the ad from being viewable by Data Providers. Some situations may not afford use of JavaScript and in those cases, the pixel version will be recommended. Note that in many cases the referrer is cast as the ad server due to the nature of being served inside iframes, so the “masking” here is extraneous.<br />
<br />
=== Tag Examples ===<br />
<br />
<br><br />
'''IMAGE Pixel Tag''' (Static example)<br />
<syntaxhighlight lang="javascript"><br />
<img src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3&ca=cmpXXXX&cr=&pc=plcXXXX&r=[timestamp]"<br />
width="1" height="1" alt=""/><br />
</syntaxhighlight><br />
<br />
'''IMAGE Pixel Tag''' (Macro example)<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"><br />
</script><br />
</syntaxhighlight><br />
<br />
'''JavaScript Tag''' (Static example)<br />
<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3mr=1&ty=js&ca=cmpXXXX&cr=&pc=plcXXXX&r=[timestamp]"<br />
></script><br />
</syntaxhighlight><br />
<br />
'''JavaScript Tag''' (Macro example)<br />
<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"></<br />
script><br />
</syntaxhighlight><br />
<br><br />
<br />
The Nielsen Digital Ad Ratings system also features the ability to record Viewability information such as: How long an Ad has been visible on the screen, and what portion on the Ad. This is an additional feature that can be purchased from your Nielsen Client Services Representative.<br />
<br />
Viewability for display ads can ONLY be offered through the JavaScript tag. If you select this service, the following is an example of the tag that will be provided to you by the Nielsen Digital Implementation Team:<br />
<br />
'''JavaScript with Viewability for display ads:'''<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"></<br />
script><br />
</syntaxhighlight><br />
<br />
<blockquote>The above tag is just examples and should not be placed in any live site or ad server. You will be provided with tags specifically designed for your media plan/campaign or be able to download tags after creation in CMI (Campaign Management Interface)</blockquote><br />
<br />
== Standard DAR Tag ==<br />
The DAR tag is available as a 1x1 pixel. The following pixel/tag parameters must be specified for all DAR tags, 1x1, regardless of implementation type: browser, mobile browser, mobile app or connected device.<br />
<br />
{| class="wikitable" <br />
|-<br />
! Tag Parameter<br />
! Description<br />
|-<br />
| CI<br />
| Client ID: the ID that is associated with the DAR account that processed tag data is associated with. Will always be hardcoded to a Nielsen generated value that comes from the Nielsen campaign management system<br />
|- style="background-color:#eff8ef;"<br />
| AM<br />
| Ad Server: an ad server participating on the campaign media-plan. This is an internal Nielsen generated value when the ad server is indicated on the campaign during setup<br />
|-<br />
| CA<br />
| Campaign Id: this is the ID associated with your DAR campaign. Unless you are creating and managing the Nielsen campaign via the DAR Tag API, then this parameter value will always be generated from the Nielsen campaign management system. Note: often maps to a media-plan I/O Id<br />
|- style="background-color:#eff8ef;"<br />
| CR<br />
| Creative Id: DAR does not currently report at the creative level; can be hard coded ad server id or associated with a macro expansion<br />
|-<br />
| PC<br />
| Placement Id: can be generated by the ad server via macro expansion or generated by the Nielsen campaign management system. Note: often maps to one of Ad Unit Id, Line Item Id or Video Ad Id<br />
|- style="background-color:#eff8ef;"<br />
| CE<br />
| Site Id: the Id that identifies a publisher site that the placement needs to be mapped to. Maps into the Nielsen MarketView database. Note: can be hardcoded to a pre-registered ad server site id in the Nielsen system or a macro expansion where more than one pre-existing site ids have been made known to Nielsen<br />
|-<br />
| R<br />
| Cachebuster (web): timestamp / random number. Generated by ad server<br />
|- style="background-color:#eff8ef;"<br />
| AT<br />
| Fixed value: “view”<br />
|-<br />
| RT<br />
| Fixed value: “banner”<br />
|- style="background-color:#eff8ef;"<br />
| ST<br />
| Fixed value: “image”<br />
|}<br />
<blockquote> Do not URL encode the values</blockquote><br />
<br />
== Additional Parameters ==<br />
In this section we describe the additional parameters that the DAR tag can support, specifically Hashed Email, UID2 values, along with Page URL and Bundle Identifier if available. Please work with your Nielsen Technical Account Manager on deciding which of the following parameters to append to the standard DAR tag. <br />
<br />
'''Web Browser DAR tag (cookie based persons identification)'''<br />
<br />
[https://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=nlsn_plc0001&ce=000&r=34245454 https://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=<siteid>&r=<timestamp>]<br />
<br />
'''Web Browser PLUS tag'''<br />
<br />
[http://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=554554_plc0001&ce=0000 http://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=0000]&hem_sha256=<value>&uid2=<value>&uid_token=<value>&si=<value>c68=bndlid,com.tam.nielsen.com<br />
<br />
=== HEM Support (Hashed Email) ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"| Hashed Email <br />
| User’s email address that has been run through a hashing algorithm (e.g. SHA256, MD5, SHA1) </br> to create a unique string. If a client is unable to determine hashing type, they should pass using &hem_unknown parameter.<br />
|style="width: 20%"|<code>&hem_unknown</br>&hem_sha256</br>&hem_md5</br>&hem_sha1</code><br />
|}<br />
<br />
<blockquote>Please use the parameter that matches your hashing algorithm.<br> For example, if you are using sha256 to encode the email address, then use <code>hem_sha256={encrypted_value_here}</code><br />
</blockquote><br />
Example:<br />
<syntaxhighlight lang="javascript"><br />
hem_sha256=tMmiiTI7IaAcPpQPFQ65uMVCWH8av9jw4cwf/F5HVRQ=<br />
</syntaxhighlight><br />
<br />
=== Unified ID ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"| Unified ID 2.0<br />
| An identifier based on a user’s verifiable PII (e.g. hashed email). UID2.0 was initially created by The Trade Desk (TTD)</br> and is now managed by Prebid. For more information on UID2.0 : https://github.com/UnifiedID2/uid2docs<br />
| &uid2<br />
|-<br />
| Unified ID 2.0 Token<br />
| Encrypted Unified ID 2.0<br />
| &uid_token<br />
|}<br />
<br />
Example:<br />
<syntaxhighlight lang="javascript"><br />
uid2=MTKVpUAzwYAPnHrtfE0wlINOMzhU7UUEjjVdCdRu63k=<br />
uid_token=AgAAAAPFR0zA5ogv/yaAPiUsAdZPsfqS8QlDSGxAB+rr8yekFs3AjLYVk5qqqiyV2XHbSuwzHmxSlLeQeKQI1mp015jsNnpX5/xGgXldcgVz+gFnyh3T8/3agMwRmyrhCxG4oH2C7<br />
fc48AQk2eotE7FW0ZDEYM8fD9ZxDaxFUC/OV3OuZA&<br />
</syntaxhighlight><br />
<br />
=== Page and Bundle ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"|Page URL<br />
| style="width: 65%"| Canonical URL of the content where the Ad creative is served. (e.g. https://example.com/news/tech/article.html) The parameter value has to be encoded with JavaScript’s encodeURIComponent() method or equivalent. <br />Example: si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
| &si<br />
|-<br />
| App Bundle ID<br />
| The app’s unique bundle ID (e.g. com.example.myapp). The ID can be used to look up the App in Apple’s App Store</br> or the Google Play Store. References:https://developer.android.com/studio/build/application-idhttps://developer.apple.com/documentation/appstoreconnectapi/bundle_ids<br />
| &c68=bndlid,<br />
|}<br />
<br />
Example:<br />
<syntaxhighlight><br />
si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
c68=bndlid,com.tam.nielsen.com<br />
</syntaxhighlight><br />
<br />
== Supported Creative Types ==<br />
<br />
For consistency, Nielsen recommends tagging as much of the campaign creative types as possible, including site-served elements. '''Note:''' Nielsen may need to review/test on a case-by-case basis.<br />
<br />
Nielsen Digital Ad Ratings supports banner ads, rich media and video units that are capable of being tagged with a 3rd party tracking pixel.<br />
<blockquote>Some examples of non-standard campaign items that may be tagged include:<br />
* microsite pages<br />
* site “skins’”<br />
* online mini-games<br />
* streaming video<br />
* pre-roll video banners<br />
</blockquote><br />
Most often, these items will need to be site served and our pixel will need to be provided to the site to implement directly.<br />
<blockquote>The following are items not tagged:<br />
* click command/text links<br />
* default/backup ads in a 3rd party ad server<br />
* static ‘logo’ creatives<br />
</blockquote><br />
<br />
Digital Ad Ratings Viewability Solution: All standard ad units listed under [http://www.iab.net/displayguidelines Universal Ad Package (UAP)] on are supported for Viewability.<br />
<br />
Placements and sites that cannot support JavaScript cannot support Viewability.<br />
<br />
'''‘Best Practices’ for Video Tags:''' Nielsen recommends all video tags be deployed as close to the beginning of the video stream as possible (post buffer).<br />
Placements delivering to Flash creative should have our tag implemented within the Flash code.<br />
<br />
== How the Tag Works ==<br />
<br />
The following describes the masked javascript version of the tag. <br><br />
For the non-masked pixel version of the tag, steps 5-8 would be collapsed to just 2 steps.<br />
<br />
[[File:image3-dar.png|right|500px]]<br />
# End-user uses her web browser to visit a website that contains an ad creative being measured by Nielsen.<br />
# Website sends web page back to end-user. (Web page contains HTML describing web content & ads)<br />
# End-user’s web browser requests the ad creative from Ad Server<br />
# Ad Server sends an iframe ad creative back to the end-user which contains the Nielsen measurement tag<br />
# End-user’s web browser makes a request to the Nielsen servers.<br />
## The tag’s HTTP request contains a campaign ID and placement, which is collected by Nielsen<br />
## The Nielsen system checks the user’s machine for an opt-out cookie – if one exists the process ends here<br />
## The Nielsen system checks to see if the campaign value in the tag was selected for Viewability. If so it downloads the Integral Ad Science tag to the end-user’s browser.<br />
# Nielsen server sends JavaScript code back to end-user’s web browser, including a 1x1 pixel.<br />
# End-user’s web browser executes JavaScript code and makes an iframe request to Nielsen server to enable the “referrer masking redirect”<br />
# Nielsen server sends an HTML message to the end-user’s web browser.<br />
# End-user’s web browser executes HTML and requests a 1x1 pixel from the Data Provider using Nielsen server information as the HTTP referrer – thus masking the Website’s information<br />
## The campaign ID and placement ID are passed through to Data Provider in an encrypted format<br />
# If Viewability is enabled the JavaScript will download a Javascript tag that calls the viewability vendor (either Nielsen or 3rd Party) to begin tracking inview metrics.<br />
# Data Provider responds with a 1x1 pixel. End process.<br />
<br />
== '''Share Your Delivered Impressions''' ==<br />
<br />
'''Why the Media Plan is Needed'''<br />
<br />
Knowing the delivered impressions also helps Nielsen run automated QA checks, for example triggering alerts when data does not appear for a placement on an expected date. This ensures overall quality, and reduces errors in the tagging process.<br />
<br />
It is the responsibility of the client to send Nielsen an impression delivery report, generally known as the “ad server report.” Nielsen can provide the client with a template with the inputs required to complete the quality checks. If the client does not send these reports, Nielsen will not be able to complete the quality checks. Below are instructions on how to send these reports to Nielsen.<br />
<br />
'''How to Share Your Delivered impressions'''<br />
<br />
Set up an automated daily report from your ad server containing Site Name, Site ID, Placement Name, Placement ID, and data date.<br />
<br />
A secondary method to share your media plan information is to grant Nielsen “Reporting access” to your campaign in the designated ad server (such as DCM). To do this, simply grant the login [http://mailto:clientreporting@nielsen.com clientreporting@nielsen.com] access. In doing so Nielsen can directly access your media plan information, which enables us to check for updates, and reconcile any<br /><br />
discrepancies.<br />
<br />
<blockquote>Please note that Nielsen is currently in discussions with several leading Ad Servers regarding direct integration between Nielsen and the ad server platforms. Once completed this could someday enable Nielsen to retrieve Media Plans on a completed automated basis.<br />
</blockquote><br />
<br />
== '''Apply the Tag''' ==<br />
=== '''Tag Generation''' ===<br />
<br />
Your Nielsen representative will walk you through the Campaign Management Interface so that you can download tags at will at any point in the campaign.<br />
<br />
Nielsen supports macro-based tag generation for several major ad servers. Nielsen’s Technical Account Manager (TAM) can assist you in leveraging macro-based tags.<br />
<br />
=== '''Tag Application''' ===<br />
<br />
Apply the tag according to the 3rd party tracking pixel specifications of your ad server. If additional guidance is needed, please consult with the Technical Account Manager (TAM) for more specific instructions or recommendations, if available.<br />
<br />
== Special Note for Video Tags ==<br />
Nielsen’s recommended “Best Practice” for tagging your video ads is to apply the Digital Ad Ratings tag as close to the beginning of the video as possible and after initiation of the ad stream, when the ad itself begins to appear on the user’s browser, closest to the opportunity to see. To ensure video content initiates during Digital Ad Ratings measurement, tags should always be placed post buffer. Recognizing that it’s not always possible to give the Nielsen pixel priority positioning, please be aware that the placement of the tag should be discussed with the publisher/advertiser counterparty so that both sides agree on the measurement approach.<br />
<br />
In accordance with MRC requirements, Clients must append “autop” parameter to detect click to play vs auto-play to their video tags. To detect auto-refresh (page refresh), “autof” parameter must be included (not limited to video tags).<br />
<syntaxhighlight lang=javascript><br />
<img src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3&ca=cmpXXXX&cr=&pc=plcXXXX&<br />
autop=(value)&autof=(value)&r=[timestamp]" width="1" height="1" alt="" /><br />
</syntaxhighlight><br />
<br />
==== '''autop''' ====<br />
- A value of 1 will be passed when Auto-Play is detected. (e.g. autop=1)<br /><br />
- A value of 2 will be passed when Click-to-Play is detected. (e.g. autop=2)<br /><br />
- When no value or parameter is not present, impressions are labeled as Unknown Play.<br />
<br />
==== '''autof''' ====<br />
- A value of 1 will be passed when Auto-Refresh is detected. (e.g. autor=1)<br /><br />
- When no value or parameter is not present, impressions are labeled as Unknown Refresh.<br />
<br />
=== '''Special Note for Video Viewability Implementation:''' ===<br />
* Nielsen does not support any Flash based video players for viewability measurement.<br />
* The ad and tag must be in the same division (div tag) in order to track Viewability<br />
* Video:<br />
** VPAID compliant players<br />
** HTML5 Players (Flash not supported)<br />
** VPAID or mp4 creative<br />
** Video player must support VPAID and mp4<br />
<br />
=== '''Workflow and Tag Requirements for Nielsen Viewability with Qualified Ad Audience''' ===<br />
The following steps represent the tag/data flow between the publisher and Nielsen, through to final reporting.<br />
<blockquote> Please note that the assigned values for <code>CA, CI, AM, AM, PC and CR </code> in the example tags below are for illustrative purposes only to demonstrate the VW viewability state tag token. These values will need to be replaced with client specific data and/or macros specific to the ad serving situation.</blockquote><br />
<br />
# Ad creative exposed to the user<br /><br />
# Ad Server technology fires DAR tag on the publisher site<br /><br />
# Viewable state detected by Nielsen technology on publisher property; tag/signal sent to Nielsen collection system<br /><br />
# Nielsen collection system generates and executes the DAR tag with one of the following viewable states.<br />
# DAR data processing and reporting aggregates viewable impression states by campaign, placement and demographic attribution.<br />
<br />
==== '''Viewability Base URL &amp; Ping Paths''' ====<br />
<code> events.imrworldwide.com/VALUE?... </code><br />
<br />
==== '''Ping Path Values''' ====<br />
* /nmp - Measure Ping<br />
* /mp - Open Viewability Measure Ping<br />
* >/psp - Primary Standard Ping<br />
* /120sp - 120 Second Ping<br />
* /cp - Cadence Ping (used by SDK)<br />
* /fp - Final Ping<br />
* /er - Error Ping<br />
<br />
==== '''Nielsen DAR Tag/VPAID Query Strings''' ====<br />
'''Measure Ping'''<br />
<syntaxhighlight lang=html><br />
/nmp?impid=VALUE&amp;ca=VALUE&amp;ci=VALUE&amp;cr=VALUE&amp;ce=VALUE&amp;pc=VALUE&amp;am=VALUE&amp;<br />
cy=VALUE&amp;meas=VALUE&amp;ss=VALUE&amp;vp=VALUE&amp;as=VALUE&amp;al=VALUE<br />
</syntaxhighlight><br />
<br />
'''Primary Standard Ping'''<br />
<syntaxhighlight lang=html><br />
/psp?impid=VALUE&amp;vs=VALUE<br />
</syntaxhighlight><br />
<br />
'''120 Second Ping'''<br />
<syntaxhighlight lang=html><br />
/120sp?impid=VALUE&amp;vs=VALUE&amp;vts=VALUE&amp;ats=VALUE<br />
</syntaxhighlight><br />
'''Finish Ping'''<br />
<syntaxhighlight lang=html><br />
/fp?impid=VALUE&amp;vs=VALUE&amp;ss=VALUE&amp;vp=VALUE&amp;as=VALUE&amp;ar=VALUE&amp;vts=VALUE&amp;ats=VALUE<br />
</syntaxhighlight><br />
'''Error Ping'''<br />
<syntaxhighlight lang=html><br />
/er?impid=VALUE&amp;ca=VALUE&amp;ci=VALUE&amp;cr=VALUE&amp;ce=VALUE&amp;pc=VALUE&amp;am=VALUE&amp;ercd=VALUE<br />
</syntaxhighlight><br />
<br />
=== '''Workflow and Tag Requirements for 3rd Party Viewability''' ===<br />
The following steps represent the tag/data flow between publisher, Nielsen and the 3rd party viewability vendor (hereafter referred to as “vendor”), through to final reporting.<br />
<br />
<blockquote>Please note that the assigned values for CA, CI, AM, AM, PC and CR in the example tags below are for illustrative purposes only to demonstrate the VW viewability state tag token. These values will need to be replaced with client specific data and/or macros specific to the ad serving situation.</blockquote><br />
<br />
'''Requirements'''<br />
* Ad creative exposed to the user<br /><br />
* Vendor technology fires DAR tag on the publisher site<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/m?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignId]&amp;cr=[creativeId/macro]<br />
&amp;pc=[placementId/macro]&amp;r=[timestamp]<br />
</syntaxhighlight><br />
* Viewable state detected by vendor detection technology (i.e. vendor Javascript containertag) on publisher property; tag/signal sent to vendor collection system<br />
* Vendor collection system generates and executes the DAR tag with one of the following viewable state (see highlight) embedded<br />
<br />
==== '''onMeasureable''' ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignI d]&amp;cr=[creativeId/macro]&amp;pc=<br />
[amvalue]_[placementId/macro]&amp;vw=meas&amp;r=[timestamp]</syntaxhighlight><br />
<br />
==== '''onInViewMRC''' ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignId]&amp;cr=[creativeId/macro]<br />
&amp;pc=[amvalue]_[placementId/macro]&amp;vw=view&amp;r=[timestamp ]</syntaxhighlight><br />
==== '''onSuspicious''' ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignI d]&amp;cr=[creativeId/macro]<br />
&amp;pc=[amvalue]_[placementId/macro]&amp;vw=susp&amp;r=[timestamp ]</syntaxhighlight><br />
<br />
* DAR data processing and reporting aggregates viewable impression states by campaign, placement and demographic attribution.<br />
<blockquote>'''Special Note for Nielsen Viewability with Qualified Ad Audience:''' Primary owner of campaign must provide assigned Technical Account Manager (TAM) VPAID tags per site/placement in order for VAST Wrapper to be delivered back to primary owner for implementation within their respective ad server, CMS, video serving platform, etc.<br />
</blockquote><br />
<br />
<blockquote>'''Special Note for Server Side Dynamic Ad Insertion:''' In cases where Server Side Dynamic Ad Insertion (SSDAI) is present, the Nielsen tag cannot execute unless the client side video player is coded to fire impression pixels when ads play. When this happens, all of the existing specifications for tag format, time, and criteria of execution (i.e. on play of ad) previously documented must be followed.<br />
</blockquote><br />
<br />
== '''QA Testing the Tag''' ==<br />
<br />
Nielsen’s Technical Account Manager (TAM) will coordinate a plan to test fire tags in advance of the campaign go-live date.<br />
<br />
In order to test the implementation of the Nielsen tag, at least one or two (more are<br /><br />
recommended) live URLs should be provided to the TAM. If a live page cannot be made available, at staging page or offline test page should be provided. The object of this is so that the TAM can see the Nielsen call being made live, exactly as it has been implemented, to verify all of the values expected – dynamic and static - are in the tag. A spot check of a couple of placements should be sufficient unless otherwise requested. In lieu of an actual test page, we may recommend you provide a screenshot of you testing the implementation from your end, showing the Nielsen call exactly as it is being called.<br />
<br />
Additionally, we will verify that the tags delivered have begun to receive data once the campaign actually goes live and will regularly (every 7-14 days, minimally) compare the Nielsen reporting to your 3rd party or publisher reporting to ensure we are capturing all of the data for all of the placements, as expected, and that the overall gap between your reporting and the Nielsen reporting is kept to a minimum.<br />
<br />
'''Detailed steps for confirming proper tag implementation'''<br />
* Open Chrome browser and enable “Developer Tools” (shortcuts: PC, “F12” - Mac, “Command+Option+I”)<br />
<blockquote>'''NOTE''' - Other browsers or debugging tools can also be used as an alternative (ie Firefox w/HttpFox extension, Fiddler, Charles, Wireshark, etc).</blockquote><br />
* Paste test page into browser URL field<br />
* Toggle to the “Network” tab<br />
** To isolate the DAR ping you can also input “imr” into the filter box<br />
[[File:image4-dar.png|900px]]<br />
<br />
<blockquote>'''TIP''' - If DAR tag does not display try refreshing the test page</blockquote><br />
=== '''If IMAGE tags were used''' ===<br />
'''Confirm call status is 302'''<br />
This ensures a redirect has been made to our Data Enrichment Provider<br />
[[File:image5-dar.png|600px]]<br />
<br />
'''Clicking on the call and navigating to the “Headers” tab will allow you to better evaluate tag construction'''<br />
[[File:image6-dar.png|500px]]<br />
<br />
'''The “Query String” section will disclose the tag parameter'''<br />
Confirm these values are displaying as expected<br />
<blockquote>'''NOTE''' - If ad server macro tokens are used, please ensure they are expanding properly<br />
</blockquote><br />
[[File:image7-dar.png|600px]]<br />
<br />
'''Optional - Review Data Enrichment Provider call'''<br />
his can be identified by searching for “brandlift”<br />
[[File:image8-dar.png|594px]]<br />
Call status should be 200<br />
<br />
<blockquote>'''NOTE''' - campaign tag parameters are encrypted when passed to Data Enrichment Provider</blockquote><br />
[[File:image9-dar.png|600px]]<br />
<br />
=== '''If JavaScript tags were used''' ===<br />
<br />
Steps are same as the above except for the following:<br />
* Two Nielsen (“imr”) calls will be made, both with status of 200<br />
** 1st - logs the impression on Nielsen servers<br />
** 2nd - initiates the call to our Data Enrichment Provider<br />
[[File:image10-dar.png|592px]]<br />
* 3rd (Optional) call is the same as above, review Data Enrichment Provider ping. This can be identified by searching for “brandlift”<br />
[[File:image11-dar.png|580px]]<br />
<br />
== '''Managing Campaign Updates''' ==<br />
<br />
As part of the campaign monitoring process, your Nielsen TAM will stay in close contact with you throughout the campaign, including scheduling periodic check-ins to check on the campaigns (approximately every 7-14 days, but could be more often, as needed). If you have provided reporting access to the campaign via your 3rd party or have scheduled a report to be delivered on a regular (weekly) basis, this can significantly expedite the monitoring of your campaign.<br />
<br />
If you have any questions regarding setting up the reporting to be delivered, fields that will need to be included, etc., please reach out to the TAM assigned to your campaign. If not providing direct access to reporting, please schedule reporting to be delivered on a weekly basis.<br />
</blockquote><br />
<br />
== '''Frequently Asked Questions''' ==<br />
<br />
'''What is a tag?'''<br />
<br />
For our purposes, a tag is an HTML code that is placed directly on a website or inside a 3rd party ad server to track exposure to an online advertisement. Adding the Nielsen tag to the<br /><br />
banners/videos/etc. is referred to in general as ‘tagging a campaign’.<br />
<br />
'''What is served by the Nielsen tag?'''<br />
<br />
The tag call is a simple 1x1 pixel image call. There is not a survey delivered at the time of ad call so this is not intrusive to the end user and should not adversely affect site page load times. <br />
<br />
'''What should be tagged?'''<br />
<br />
As much of the campaign that can be tagged, should be, for consistency. In most cases, we generally do not tag items such as: click command/text links, default/backup ads in a 3rd party ad server, or static ‘logo’ creatives. Whenever possible, we will request that you attempt to tag all other creative types, including site-served elements.<br />
<br />
'''Is there a way to differentiate between video “auto-play” and “click-to-play” impressions?'''<br />
<br />
The Nielsen pixel does not gather this type of granularity if the events are both sharing the same ad server placement ID. If it is desirable to compare the performance between these two events, our recommendation is to traffic these as individual placements within your ad serving<br /><br />
technology.<br />
<br />
'''What is the best way to add the Nielsen tag to my campaign?'''<br />
<br />
The Nielsen pixel should be called as close to the same time as the banner ad/creative element on which you would like to track exposure. Typically, this is handled by placing our tag inside a 3rd party ad server, such as Google’s DCM or a Rich Media vendor, such as PointRoll. However, if need be, our tag can be placed directly on a site page, immediately after the ad call in the same &lt;/div&gt; as the creative file. Further instruction can be provided on the kickoff call or we can work directly with trafficking contact(s) to get the tags in place.<br />
<br />
'''Do we need to use a 3rd party ad server to use the Nielsen tag?'''<br />
<br />
The short answer is no. In a lot of cases, we have provided a tag that can be implemented directly on a site. The benefit of placing our tag inside a 3rd party ad server is that we can provide a single tag (or minimal number of tags) that contain macros to simplify the tagging process.<br />
<br />
'''Is there anything that can’t be tagged?'''<br />
<br />
We may need to review/test on a case-by-case basis, but realistically most campaign elements can be tagged. Most often, these items will need to be site served and our pixel will need to be provided to the site to implement directly. Some examples of non-standard campaign items that have been tagged before include: microsite pages, site ‘skins’, online mini-games, streaming video, pre-roll video banners.<br />
<br />
'''The site has told us that they can accept only one pixel for the site served element. Can we append your tag to the end of ours?'''<br />
<br />
If you are serving a DCM 1x1 pixel to track these elements of your campaign, we have a method for placing our tag behind this call, to be served as a redirect. For other situations, we may need to discuss further and consider other options.<br />
<br />
'''I’m using more than one Nielsen study/product on this campaign. Will I need multiple/different tags for each?'''<br />
<br />
You should not need separate tags for each study. To keep the tagging process simple, we have designed our products so that a single tag can be used for multiple online studies, however, your TAM needs to be informed of all studies before launch so that they can be enabled.<br />
<br />
'''How much detail can be tracked with the Nielsen tag?'''<br />
<br />
Typically, we do an overall read for these studies, but we can segment the data by site, placement, ad size or creative, for example. If more granular data is desired, this should be discussed ahead of the campaign launch and planned for at the time of tag creation. ''We cannot segment the data if we have not tagged for it'' -- multiple tags will need to be created and implemented properly. Note that this can often be a time consuming process for the client trafficker and additional time should be allotted if this is needed. Lastly, keep in mind that exposure sample size may be a factor for segmenting the data at a more granular level.<br />
<br />
'''Why is it recommended to implement a timestamp or random number on the tag?''' This value will ensure that the tag call will not be cached on a user’s browser. It’s not absolutely necessary to implement for the tag to work, but without it you may see a larger gap between the impressions ran and what Nielsen captures. It is recommended to minimize this gap.<br />
<br />
'''For campaigns involving Facebook, what can’t be tagged on their site?'''<br />
<br />
Fan/Like pages are not allowed to be tagged, per Facebook. Additionally, Marketplace slots are not allowed to be tagged as these are user generated ads.<br />
<br />
'''What if it is not possible to provide a test or staging page before launch?'''<br />
<br />
While not ideal, we can view raw impression numbers on the day of the launch as well as review a live example if a URL is provided. Another option would to test from the client/site side and provide a screenshot of the Nielsen call being made using a proxy tool (HTTPWatch, Fiddler, Charles, etc.) – prior to launch. The aim either way is to minimize missing impressions for your campaign, so it is in your best interest to provide for this testing if you can.<br />
<br />
'''What is considered to be an acceptable gap in reporting?'''<br />
<br />
In a perfect world, we’d like to see no gap in the numbers. We realize this is simply not possible – it is a factor of the Internet and having different counting methodologies, so we will aim for the lowest overall gap we can. Even with everything trafficked correctly; it is not uncommon to see gaps in the range of 5 to 10%, so we shoot for this range (if it’s lower than that, that’s great). If it’s greater than 10%, it usually indicates that there was something that was missed from being tagged or there’s an additional issue that requires further attention. When issues arise, we make all attempts to highlight and communicate the issue seen, to minimize the overall impact to the study, but are reliant on the client to ensure the issue is fixed. In a campaign where there are issues such as this, we try to keep the gap under 20% and will document any issues found. What are the capabilities for tagging video and video based ads?<br />
<br />
Our tag is not a specific limitation as it is one of the simplest things that can be served – a 1x1 image. That being said, much of the video implementation limitations are often dictated by the video vendors themselves. Where you can add our tag is dependent on the capabilities of these vendors. Some have the ability to place the tag in multiple locations in the video (i.e. beginning, middle, end – multiple tags will be needed to separate these out) and some simply place the pixel directly on the webpage, next to video being served. Further discussion may need to happen with the vendor, Nielsen and the client to determine the optimum implementation that meets the client's needs.<br />
</blockquote></div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DAR_Tag_Implementation_Guide&diff=5635DAR Tag Implementation Guide2022-02-10T17:38:24Z<p>LaMarHolmes: /* HEM Support (Hashed Email) */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
<br />
== Introduction ==<br />
<br />
Nielsen Digital Ad Ratings is a measurement platform for online advertising campaigns. The platform provides a clear view of the true audience of a campaign, including '''Reach''', '''Frequency''', and '''GRP''' statistics by audience demographic group.<br />
<br />
The key innovation of the platform is the inclusion of demographic data from leading web publishers to attach actual user demographics to ad impressions.<br />
<br />
The diagram below summarizes how the Nielsen tag measures the ad campaign:<br />
# Advertiser places ads on one or more websites<br />
#Website displays ad to a user<br />
#Nielsen tag counts impressions and controls redirect to the Data Enrichment Provider<br />
[[File:dar-image2.png|900px]]<br />
<br />
<br />
=== Support for Other Nielsen Ad Effectiveness Products ===<br />
<br />
The tag used for Nielsen Digital Ad Ratings is compatible for all Nielsen Ad Effectiveness products, including (but not limited to) Brand Effect Extended View, Response Effect, and Sales Effect.<br />
<br />
=== User Experience ===<br />
<br />
The tags described in this document are used only to measure audience exposure to advertisements; they do not launch a survey, and have no impact on the user experience. Typical response time for the tag is on par with industry standards and because the code executed is simple and fires after the ad loads, they are transparent to the user.<br />
<br />
For further information on survey-based products, or any other products, please contact your Client Services Manager.<br />
__TOC__<br />
<br />
== Available Tag Versions ==<br />
<br />
The Nielsen Digital Ad Ratings system offers 2 basic types of ad tags<br />
<br />
* '''IMAGE (1X1) Pixel'''<br />
This is the simplest version of the tag, generally for use by clients who cannot accept JavaScript format tags or have limited options for implementation. Itincludes encryption, but does not utilize referrer masking.<br />
<br />
* '''JavaScript Tag'''<br />
This is a more complex tag which includes encryption and masking of referrer site via a script call. This Tag may also be used to measure Viewability metrics.<br />
There may be additional functionality offered by this format in future releases as well.<br />
* '''Ad Networks''' This tag includes additional functionality to scrape the URL of the hosting website if associated to an ad network within the Nielsen system. Keep in mind URLs captured will only be used for “site adjustment factors” and not be included in any reporting<br />
<br />
<blockquote>'''NOTE''' - Both tag types support macros and are available in secure and non-secure formats. Please reach out to your Nielsen Technical Account Manager for additional information.</blockquote><br />
<br />
While the IMAGE pixels are easiest to implement, the JavaScript versions are recommended because they provide the highest level of confidentiality by masking the source of the ad from being viewable by Data Providers. Some situations may not afford use of JavaScript and in those cases, the pixel version will be recommended. Note that in many cases the referrer is cast as the ad server due to the nature of being served inside iframes, so the “masking” here is extraneous.<br />
<br />
=== Tag Examples ===<br />
<br />
<br><br />
'''IMAGE Pixel Tag''' (Static example)<br />
<syntaxhighlight lang="javascript"><br />
<img src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3&ca=cmpXXXX&cr=&pc=plcXXXX&r=[timestamp]"<br />
width="1" height="1" alt=""/><br />
</syntaxhighlight><br />
<br />
'''IMAGE Pixel Tag''' (Macro example)<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"><br />
</script><br />
</syntaxhighlight><br />
<br />
'''JavaScript Tag''' (Static example)<br />
<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3mr=1&ty=js&ca=cmpXXXX&cr=&pc=plcXXXX&r=[timestamp]"<br />
></script><br />
</syntaxhighlight><br />
<br />
'''JavaScript Tag''' (Macro example)<br />
<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"></<br />
script><br />
</syntaxhighlight><br />
<br><br />
<br />
The Nielsen Digital Ad Ratings system also features the ability to record Viewability information such as: How long an Ad has been visible on the screen, and what portion on the Ad. This is an additional feature that can be purchased from your Nielsen Client Services Representative.<br />
<br />
Viewability for display ads can ONLY be offered through the JavaScript tag. If you select this service, the following is an example of the tag that will be provided to you by the Nielsen Digital Implementation Team:<br />
<br />
'''JavaScript with Viewability for display ads:'''<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"></<br />
script><br />
</syntaxhighlight><br />
<br />
<blockquote>The above tag is just examples and should not be placed in any live site or ad server. You will be provided with tags specifically designed for your media plan/campaign or be able to download tags after creation in CMI (Campaign Management Interface)</blockquote><br />
<br />
== Standard DAR Tag ==<br />
The DAR tag is available as a 1x1 pixel. The following pixel/tag parameters must be specified for all DAR tags, 1x1, regardless of implementation type: browser, mobile browser, mobile app or connected device.<br />
<br />
{| class="wikitable" <br />
|-<br />
! Tag Parameter<br />
! Description<br />
|-<br />
| CI<br />
| Client ID: the ID that is associated with the DAR account that processed tag data is associated with. Will always be hardcoded to a Nielsen generated value that comes from the Nielsen campaign management system<br />
|- style="background-color:#eff8ef;"<br />
| AM<br />
| Ad Server: an ad server participating on the campaign media-plan. This is an internal Nielsen generated value when the ad server is indicated on the campaign during setup<br />
|-<br />
| CA<br />
| Campaign Id: this is the ID associated with your DAR campaign. Unless you are creating and managing the Nielsen campaign via the DAR Tag API, then this parameter value will always be generated from the Nielsen campaign management system. Note: often maps to a media-plan I/O Id<br />
|- style="background-color:#eff8ef;"<br />
| CR<br />
| Creative Id: DAR does not currently report at the creative level; can be hard coded ad server id or associated with a macro expansion<br />
|-<br />
| PC<br />
| Placement Id: can be generated by the ad server via macro expansion or generated by the Nielsen campaign management system. Note: often maps to one of Ad Unit Id, Line Item Id or Video Ad Id<br />
|- style="background-color:#eff8ef;"<br />
| CE<br />
| Site Id: the Id that identifies a publisher site that the placement needs to be mapped to. Maps into the Nielsen MarketView database. Note: can be hardcoded to a pre-registered ad server site id in the Nielsen system or a macro expansion where more than one pre-existing site ids have been made known to Nielsen<br />
|-<br />
| R<br />
| Cachebuster (web): timestamp / random number. Generated by ad server<br />
|- style="background-color:#eff8ef;"<br />
| AT<br />
| Fixed value: “view”<br />
|-<br />
| RT<br />
| Fixed value: “banner”<br />
|- style="background-color:#eff8ef;"<br />
| ST<br />
| Fixed value: “image”<br />
|}<br />
<blockquote> Do not URL encode the values</blockquote><br />
<br />
== Additional Parameters ==<br />
In this section we describe the additional parameters that the DAR tag can support, specifically Hashed Email, UID2 values, along with Page URL and Bundle Identifier if available. Please work with your Nielsen Technical Account Manager on deciding which of the following parameters to append to the standard DAR tag. <br />
<br />
'''Web Browser DAR tag (cookie based persons identification)'''<br />
<br />
[https://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=nlsn_plc0001&ce=000&r=34245454 https://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=<siteid>&r=<timestamp>]<br />
<br />
'''Web Browser PLUS tag'''<br />
<br />
[http://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=554554_plc0001&ce=0000 http://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=0000]&hem_sha256=<value>&uid2=<value>&uid_token=<value>&si=<value>c68=bndlid,com.tam.nielsen.com<br />
<br />
=== HEM Support (Hashed Email) ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"| Hashed Email <br />
| User’s email address that has been run through a hashing algorithm (e.g. SHA256, MD5, SHA1) </br> to create a unique hexadecimal string. If a client is unable to determine hashing type, they should pass using &hem_unknown parameter.<br />
|style="width: 20%"|<code>&hem_unknown</br>&hem_sha256</br>&hem_md5</br>&hem_sha1</code><br />
|}<br />
<br />
<blockquote>Please use the parameter that matches your hashing algorithm.<br> For example, if you are using sha256 to encode the email address, then use <code>hem_sha256={encrypted_value_here}</code><br />
</blockquote><br />
Example:<br />
<syntaxhighlight lang="javascript"><br />
hem_sha256=tMmiiTI7IaAcPpQPFQ65uMVCWH8av9jw4cwf/F5HVRQ=<br />
</syntaxhighlight><br />
<br />
=== Unified ID ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"| Unified ID 2.0<br />
| An identifier based on a user’s verifiable PII (e.g. hashed email). UID2.0 was initially created by The Trade Desk (TTD)</br> and is now managed by Prebid. For more information on UID2.0 : https://github.com/UnifiedID2/uid2docs<br />
| &uid2<br />
|-<br />
| Unified ID 2.0 Token<br />
| Encrypted Unified ID 2.0<br />
| &uid_token<br />
|}<br />
<br />
Example:<br />
<syntaxhighlight lang="javascript"><br />
uid2=MTKVpUAzwYAPnHrtfE0wlINOMzhU7UUEjjVdCdRu63k=<br />
uid_token=AgAAAAPFR0zA5ogv/yaAPiUsAdZPsfqS8QlDSGxAB+rr8yekFs3AjLYVk5qqqiyV2XHbSuwzHmxSlLeQeKQI1mp015jsNnpX5/xGgXldcgVz+gFnyh3T8/3agMwRmyrhCxG4oH2C7<br />
fc48AQk2eotE7FW0ZDEYM8fD9ZxDaxFUC/OV3OuZA&<br />
</syntaxhighlight><br />
<br />
=== Page and Bundle ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"|Page URL<br />
| style="width: 65%"| Canonical URL of the content where the Ad creative is served. (e.g. https://example.com/news/tech/article.html) The parameter value has to be encoded with JavaScript’s encodeURIComponent() method or equivalent. <br />Example: si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
| &si<br />
|-<br />
| App Bundle ID<br />
| The app’s unique bundle ID (e.g. com.example.myapp). The ID can be used to look up the App in Apple’s App Store</br> or the Google Play Store. References:https://developer.android.com/studio/build/application-idhttps://developer.apple.com/documentation/appstoreconnectapi/bundle_ids<br />
| &c68=bndlid,<br />
|}<br />
<br />
Example:<br />
<syntaxhighlight><br />
si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
c68=bndlid,com.tam.nielsen.com<br />
</syntaxhighlight><br />
<br />
== Supported Creative Types ==<br />
<br />
For consistency, Nielsen recommends tagging as much of the campaign creative types as possible, including site-served elements. '''Note:''' Nielsen may need to review/test on a case-by-case basis.<br />
<br />
Nielsen Digital Ad Ratings supports banner ads, rich media and video units that are capable of being tagged with a 3rd party tracking pixel.<br />
<blockquote>Some examples of non-standard campaign items that may be tagged include:<br />
* microsite pages<br />
* site “skins’”<br />
* online mini-games<br />
* streaming video<br />
* pre-roll video banners<br />
</blockquote><br />
Most often, these items will need to be site served and our pixel will need to be provided to the site to implement directly.<br />
<blockquote>The following are items not tagged:<br />
* click command/text links<br />
* default/backup ads in a 3rd party ad server<br />
* static ‘logo’ creatives<br />
</blockquote><br />
<br />
Digital Ad Ratings Viewability Solution: All standard ad units listed under [http://www.iab.net/displayguidelines Universal Ad Package (UAP)] on are supported for Viewability.<br />
<br />
Placements and sites that cannot support JavaScript cannot support Viewability.<br />
<br />
'''‘Best Practices’ for Video Tags:''' Nielsen recommends all video tags be deployed as close to the beginning of the video stream as possible (post buffer).<br />
Placements delivering to Flash creative should have our tag implemented within the Flash code.<br />
<br />
== How the Tag Works ==<br />
<br />
The following describes the masked javascript version of the tag. <br><br />
For the non-masked pixel version of the tag, steps 5-8 would be collapsed to just 2 steps.<br />
<br />
[[File:image3-dar.png|right|500px]]<br />
# End-user uses her web browser to visit a website that contains an ad creative being measured by Nielsen.<br />
# Website sends web page back to end-user. (Web page contains HTML describing web content & ads)<br />
# End-user’s web browser requests the ad creative from Ad Server<br />
# Ad Server sends an iframe ad creative back to the end-user which contains the Nielsen measurement tag<br />
# End-user’s web browser makes a request to the Nielsen servers.<br />
## The tag’s HTTP request contains a campaign ID and placement, which is collected by Nielsen<br />
## The Nielsen system checks the user’s machine for an opt-out cookie – if one exists the process ends here<br />
## The Nielsen system checks to see if the campaign value in the tag was selected for Viewability. If so it downloads the Integral Ad Science tag to the end-user’s browser.<br />
# Nielsen server sends JavaScript code back to end-user’s web browser, including a 1x1 pixel.<br />
# End-user’s web browser executes JavaScript code and makes an iframe request to Nielsen server to enable the “referrer masking redirect”<br />
# Nielsen server sends an HTML message to the end-user’s web browser.<br />
# End-user’s web browser executes HTML and requests a 1x1 pixel from the Data Provider using Nielsen server information as the HTTP referrer – thus masking the Website’s information<br />
## The campaign ID and placement ID are passed through to Data Provider in an encrypted format<br />
# If Viewability is enabled the JavaScript will download a Javascript tag that calls the viewability vendor (either Nielsen or 3rd Party) to begin tracking inview metrics.<br />
# Data Provider responds with a 1x1 pixel. End process.<br />
<br />
== '''Share Your Delivered Impressions''' ==<br />
<br />
'''Why the Media Plan is Needed'''<br />
<br />
Knowing the delivered impressions also helps Nielsen run automated QA checks, for example triggering alerts when data does not appear for a placement on an expected date. This ensures overall quality, and reduces errors in the tagging process.<br />
<br />
It is the responsibility of the client to send Nielsen an impression delivery report, generally known as the “ad server report.” Nielsen can provide the client with a template with the inputs required to complete the quality checks. If the client does not send these reports, Nielsen will not be able to complete the quality checks. Below are instructions on how to send these reports to Nielsen.<br />
<br />
'''How to Share Your Delivered impressions'''<br />
<br />
Set up an automated daily report from your ad server containing Site Name, Site ID, Placement Name, Placement ID, and data date.<br />
<br />
A secondary method to share your media plan information is to grant Nielsen “Reporting access” to your campaign in the designated ad server (such as DCM). To do this, simply grant the login [http://mailto:clientreporting@nielsen.com clientreporting@nielsen.com] access. In doing so Nielsen can directly access your media plan information, which enables us to check for updates, and reconcile any<br /><br />
discrepancies.<br />
<br />
<blockquote>Please note that Nielsen is currently in discussions with several leading Ad Servers regarding direct integration between Nielsen and the ad server platforms. Once completed this could someday enable Nielsen to retrieve Media Plans on a completed automated basis.<br />
</blockquote><br />
<br />
== '''Apply the Tag''' ==<br />
=== '''Tag Generation''' ===<br />
<br />
Your Nielsen representative will walk you through the Campaign Management Interface so that you can download tags at will at any point in the campaign.<br />
<br />
Nielsen supports macro-based tag generation for several major ad servers. Nielsen’s Technical Account Manager (TAM) can assist you in leveraging macro-based tags.<br />
<br />
=== '''Tag Application''' ===<br />
<br />
Apply the tag according to the 3rd party tracking pixel specifications of your ad server. If additional guidance is needed, please consult with the Technical Account Manager (TAM) for more specific instructions or recommendations, if available.<br />
<br />
== Special Note for Video Tags ==<br />
Nielsen’s recommended “Best Practice” for tagging your video ads is to apply the Digital Ad Ratings tag as close to the beginning of the video as possible and after initiation of the ad stream, when the ad itself begins to appear on the user’s browser, closest to the opportunity to see. To ensure video content initiates during Digital Ad Ratings measurement, tags should always be placed post buffer. Recognizing that it’s not always possible to give the Nielsen pixel priority positioning, please be aware that the placement of the tag should be discussed with the publisher/advertiser counterparty so that both sides agree on the measurement approach.<br />
<br />
In accordance with MRC requirements, Clients must append “autop” parameter to detect click to play vs auto-play to their video tags. To detect auto-refresh (page refresh), “autof” parameter must be included (not limited to video tags).<br />
<syntaxhighlight lang=javascript><br />
<img src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3&ca=cmpXXXX&cr=&pc=plcXXXX&<br />
autop=(value)&autof=(value)&r=[timestamp]" width="1" height="1" alt="" /><br />
</syntaxhighlight><br />
<br />
==== '''autop''' ====<br />
- A value of 1 will be passed when Auto-Play is detected. (e.g. autop=1)<br /><br />
- A value of 2 will be passed when Click-to-Play is detected. (e.g. autop=2)<br /><br />
- When no value or parameter is not present, impressions are labeled as Unknown Play.<br />
<br />
==== '''autof''' ====<br />
- A value of 1 will be passed when Auto-Refresh is detected. (e.g. autor=1)<br /><br />
- When no value or parameter is not present, impressions are labeled as Unknown Refresh.<br />
<br />
=== '''Special Note for Video Viewability Implementation:''' ===<br />
* Nielsen does not support any Flash based video players for viewability measurement.<br />
* The ad and tag must be in the same division (div tag) in order to track Viewability<br />
* Video:<br />
** VPAID compliant players<br />
** HTML5 Players (Flash not supported)<br />
** VPAID or mp4 creative<br />
** Video player must support VPAID and mp4<br />
<br />
=== '''Workflow and Tag Requirements for Nielsen Viewability with Qualified Ad Audience''' ===<br />
The following steps represent the tag/data flow between the publisher and Nielsen, through to final reporting.<br />
<blockquote> Please note that the assigned values for <code>CA, CI, AM, AM, PC and CR </code> in the example tags below are for illustrative purposes only to demonstrate the VW viewability state tag token. These values will need to be replaced with client specific data and/or macros specific to the ad serving situation.</blockquote><br />
<br />
# Ad creative exposed to the user<br /><br />
# Ad Server technology fires DAR tag on the publisher site<br /><br />
# Viewable state detected by Nielsen technology on publisher property; tag/signal sent to Nielsen collection system<br /><br />
# Nielsen collection system generates and executes the DAR tag with one of the following viewable states.<br />
# DAR data processing and reporting aggregates viewable impression states by campaign, placement and demographic attribution.<br />
<br />
==== '''Viewability Base URL &amp; Ping Paths''' ====<br />
<code> events.imrworldwide.com/VALUE?... </code><br />
<br />
==== '''Ping Path Values''' ====<br />
* /nmp - Measure Ping<br />
* /mp - Open Viewability Measure Ping<br />
* >/psp - Primary Standard Ping<br />
* /120sp - 120 Second Ping<br />
* /cp - Cadence Ping (used by SDK)<br />
* /fp - Final Ping<br />
* /er - Error Ping<br />
<br />
==== '''Nielsen DAR Tag/VPAID Query Strings''' ====<br />
'''Measure Ping'''<br />
<syntaxhighlight lang=html><br />
/nmp?impid=VALUE&amp;ca=VALUE&amp;ci=VALUE&amp;cr=VALUE&amp;ce=VALUE&amp;pc=VALUE&amp;am=VALUE&amp;<br />
cy=VALUE&amp;meas=VALUE&amp;ss=VALUE&amp;vp=VALUE&amp;as=VALUE&amp;al=VALUE<br />
</syntaxhighlight><br />
<br />
'''Primary Standard Ping'''<br />
<syntaxhighlight lang=html><br />
/psp?impid=VALUE&amp;vs=VALUE<br />
</syntaxhighlight><br />
<br />
'''120 Second Ping'''<br />
<syntaxhighlight lang=html><br />
/120sp?impid=VALUE&amp;vs=VALUE&amp;vts=VALUE&amp;ats=VALUE<br />
</syntaxhighlight><br />
'''Finish Ping'''<br />
<syntaxhighlight lang=html><br />
/fp?impid=VALUE&amp;vs=VALUE&amp;ss=VALUE&amp;vp=VALUE&amp;as=VALUE&amp;ar=VALUE&amp;vts=VALUE&amp;ats=VALUE<br />
</syntaxhighlight><br />
'''Error Ping'''<br />
<syntaxhighlight lang=html><br />
/er?impid=VALUE&amp;ca=VALUE&amp;ci=VALUE&amp;cr=VALUE&amp;ce=VALUE&amp;pc=VALUE&amp;am=VALUE&amp;ercd=VALUE<br />
</syntaxhighlight><br />
<br />
=== '''Workflow and Tag Requirements for 3rd Party Viewability''' ===<br />
The following steps represent the tag/data flow between publisher, Nielsen and the 3rd party viewability vendor (hereafter referred to as “vendor”), through to final reporting.<br />
<br />
<blockquote>Please note that the assigned values for CA, CI, AM, AM, PC and CR in the example tags below are for illustrative purposes only to demonstrate the VW viewability state tag token. These values will need to be replaced with client specific data and/or macros specific to the ad serving situation.</blockquote><br />
<br />
'''Requirements'''<br />
* Ad creative exposed to the user<br /><br />
* Vendor technology fires DAR tag on the publisher site<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/m?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignId]&amp;cr=[creativeId/macro]<br />
&amp;pc=[placementId/macro]&amp;r=[timestamp]<br />
</syntaxhighlight><br />
* Viewable state detected by vendor detection technology (i.e. vendor Javascript containertag) on publisher property; tag/signal sent to vendor collection system<br />
* Vendor collection system generates and executes the DAR tag with one of the following viewable state (see highlight) embedded<br />
<br />
==== '''onMeasureable''' ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignI d]&amp;cr=[creativeId/macro]&amp;pc=<br />
[amvalue]_[placementId/macro]&amp;vw=meas&amp;r=[timestamp]</syntaxhighlight><br />
<br />
==== '''onInViewMRC''' ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignId]&amp;cr=[creativeId/macro]<br />
&amp;pc=[amvalue]_[placementId/macro]&amp;vw=view&amp;r=[timestamp ]</syntaxhighlight><br />
==== '''onSuspicious''' ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignI d]&amp;cr=[creativeId/macro]<br />
&amp;pc=[amvalue]_[placementId/macro]&amp;vw=susp&amp;r=[timestamp ]</syntaxhighlight><br />
<br />
* DAR data processing and reporting aggregates viewable impression states by campaign, placement and demographic attribution.<br />
<blockquote>'''Special Note for Nielsen Viewability with Qualified Ad Audience:''' Primary owner of campaign must provide assigned Technical Account Manager (TAM) VPAID tags per site/placement in order for VAST Wrapper to be delivered back to primary owner for implementation within their respective ad server, CMS, video serving platform, etc.<br />
</blockquote><br />
<br />
<blockquote>'''Special Note for Server Side Dynamic Ad Insertion:''' In cases where Server Side Dynamic Ad Insertion (SSDAI) is present, the Nielsen tag cannot execute unless the client side video player is coded to fire impression pixels when ads play. When this happens, all of the existing specifications for tag format, time, and criteria of execution (i.e. on play of ad) previously documented must be followed.<br />
</blockquote><br />
<br />
== '''QA Testing the Tag''' ==<br />
<br />
Nielsen’s Technical Account Manager (TAM) will coordinate a plan to test fire tags in advance of the campaign go-live date.<br />
<br />
In order to test the implementation of the Nielsen tag, at least one or two (more are<br /><br />
recommended) live URLs should be provided to the TAM. If a live page cannot be made available, at staging page or offline test page should be provided. The object of this is so that the TAM can see the Nielsen call being made live, exactly as it has been implemented, to verify all of the values expected – dynamic and static - are in the tag. A spot check of a couple of placements should be sufficient unless otherwise requested. In lieu of an actual test page, we may recommend you provide a screenshot of you testing the implementation from your end, showing the Nielsen call exactly as it is being called.<br />
<br />
Additionally, we will verify that the tags delivered have begun to receive data once the campaign actually goes live and will regularly (every 7-14 days, minimally) compare the Nielsen reporting to your 3rd party or publisher reporting to ensure we are capturing all of the data for all of the placements, as expected, and that the overall gap between your reporting and the Nielsen reporting is kept to a minimum.<br />
<br />
'''Detailed steps for confirming proper tag implementation'''<br />
* Open Chrome browser and enable “Developer Tools” (shortcuts: PC, “F12” - Mac, “Command+Option+I”)<br />
<blockquote>'''NOTE''' - Other browsers or debugging tools can also be used as an alternative (ie Firefox w/HttpFox extension, Fiddler, Charles, Wireshark, etc).</blockquote><br />
* Paste test page into browser URL field<br />
* Toggle to the “Network” tab<br />
** To isolate the DAR ping you can also input “imr” into the filter box<br />
[[File:image4-dar.png|900px]]<br />
<br />
<blockquote>'''TIP''' - If DAR tag does not display try refreshing the test page</blockquote><br />
=== '''If IMAGE tags were used''' ===<br />
'''Confirm call status is 302'''<br />
This ensures a redirect has been made to our Data Enrichment Provider<br />
[[File:image5-dar.png|600px]]<br />
<br />
'''Clicking on the call and navigating to the “Headers” tab will allow you to better evaluate tag construction'''<br />
[[File:image6-dar.png|500px]]<br />
<br />
'''The “Query String” section will disclose the tag parameter'''<br />
Confirm these values are displaying as expected<br />
<blockquote>'''NOTE''' - If ad server macro tokens are used, please ensure they are expanding properly<br />
</blockquote><br />
[[File:image7-dar.png|600px]]<br />
<br />
'''Optional - Review Data Enrichment Provider call'''<br />
his can be identified by searching for “brandlift”<br />
[[File:image8-dar.png|594px]]<br />
Call status should be 200<br />
<br />
<blockquote>'''NOTE''' - campaign tag parameters are encrypted when passed to Data Enrichment Provider</blockquote><br />
[[File:image9-dar.png|600px]]<br />
<br />
=== '''If JavaScript tags were used''' ===<br />
<br />
Steps are same as the above except for the following:<br />
* Two Nielsen (“imr”) calls will be made, both with status of 200<br />
** 1st - logs the impression on Nielsen servers<br />
** 2nd - initiates the call to our Data Enrichment Provider<br />
[[File:image10-dar.png|592px]]<br />
* 3rd (Optional) call is the same as above, review Data Enrichment Provider ping. This can be identified by searching for “brandlift”<br />
[[File:image11-dar.png|580px]]<br />
<br />
== '''Managing Campaign Updates''' ==<br />
<br />
As part of the campaign monitoring process, your Nielsen TAM will stay in close contact with you throughout the campaign, including scheduling periodic check-ins to check on the campaigns (approximately every 7-14 days, but could be more often, as needed). If you have provided reporting access to the campaign via your 3rd party or have scheduled a report to be delivered on a regular (weekly) basis, this can significantly expedite the monitoring of your campaign.<br />
<br />
If you have any questions regarding setting up the reporting to be delivered, fields that will need to be included, etc., please reach out to the TAM assigned to your campaign. If not providing direct access to reporting, please schedule reporting to be delivered on a weekly basis.<br />
</blockquote><br />
<br />
== '''Frequently Asked Questions''' ==<br />
<br />
'''What is a tag?'''<br />
<br />
For our purposes, a tag is an HTML code that is placed directly on a website or inside a 3rd party ad server to track exposure to an online advertisement. Adding the Nielsen tag to the<br /><br />
banners/videos/etc. is referred to in general as ‘tagging a campaign’.<br />
<br />
'''What is served by the Nielsen tag?'''<br />
<br />
The tag call is a simple 1x1 pixel image call. There is not a survey delivered at the time of ad call so this is not intrusive to the end user and should not adversely affect site page load times. <br />
<br />
'''What should be tagged?'''<br />
<br />
As much of the campaign that can be tagged, should be, for consistency. In most cases, we generally do not tag items such as: click command/text links, default/backup ads in a 3rd party ad server, or static ‘logo’ creatives. Whenever possible, we will request that you attempt to tag all other creative types, including site-served elements.<br />
<br />
'''Is there a way to differentiate between video “auto-play” and “click-to-play” impressions?'''<br />
<br />
The Nielsen pixel does not gather this type of granularity if the events are both sharing the same ad server placement ID. If it is desirable to compare the performance between these two events, our recommendation is to traffic these as individual placements within your ad serving<br /><br />
technology.<br />
<br />
'''What is the best way to add the Nielsen tag to my campaign?'''<br />
<br />
The Nielsen pixel should be called as close to the same time as the banner ad/creative element on which you would like to track exposure. Typically, this is handled by placing our tag inside a 3rd party ad server, such as Google’s DCM or a Rich Media vendor, such as PointRoll. However, if need be, our tag can be placed directly on a site page, immediately after the ad call in the same &lt;/div&gt; as the creative file. Further instruction can be provided on the kickoff call or we can work directly with trafficking contact(s) to get the tags in place.<br />
<br />
'''Do we need to use a 3rd party ad server to use the Nielsen tag?'''<br />
<br />
The short answer is no. In a lot of cases, we have provided a tag that can be implemented directly on a site. The benefit of placing our tag inside a 3rd party ad server is that we can provide a single tag (or minimal number of tags) that contain macros to simplify the tagging process.<br />
<br />
'''Is there anything that can’t be tagged?'''<br />
<br />
We may need to review/test on a case-by-case basis, but realistically most campaign elements can be tagged. Most often, these items will need to be site served and our pixel will need to be provided to the site to implement directly. Some examples of non-standard campaign items that have been tagged before include: microsite pages, site ‘skins’, online mini-games, streaming video, pre-roll video banners.<br />
<br />
'''The site has told us that they can accept only one pixel for the site served element. Can we append your tag to the end of ours?'''<br />
<br />
If you are serving a DCM 1x1 pixel to track these elements of your campaign, we have a method for placing our tag behind this call, to be served as a redirect. For other situations, we may need to discuss further and consider other options.<br />
<br />
'''I’m using more than one Nielsen study/product on this campaign. Will I need multiple/different tags for each?'''<br />
<br />
You should not need separate tags for each study. To keep the tagging process simple, we have designed our products so that a single tag can be used for multiple online studies, however, your TAM needs to be informed of all studies before launch so that they can be enabled.<br />
<br />
'''How much detail can be tracked with the Nielsen tag?'''<br />
<br />
Typically, we do an overall read for these studies, but we can segment the data by site, placement, ad size or creative, for example. If more granular data is desired, this should be discussed ahead of the campaign launch and planned for at the time of tag creation. ''We cannot segment the data if we have not tagged for it'' -- multiple tags will need to be created and implemented properly. Note that this can often be a time consuming process for the client trafficker and additional time should be allotted if this is needed. Lastly, keep in mind that exposure sample size may be a factor for segmenting the data at a more granular level.<br />
<br />
'''Why is it recommended to implement a timestamp or random number on the tag?''' This value will ensure that the tag call will not be cached on a user’s browser. It’s not absolutely necessary to implement for the tag to work, but without it you may see a larger gap between the impressions ran and what Nielsen captures. It is recommended to minimize this gap.<br />
<br />
'''For campaigns involving Facebook, what can’t be tagged on their site?'''<br />
<br />
Fan/Like pages are not allowed to be tagged, per Facebook. Additionally, Marketplace slots are not allowed to be tagged as these are user generated ads.<br />
<br />
'''What if it is not possible to provide a test or staging page before launch?'''<br />
<br />
While not ideal, we can view raw impression numbers on the day of the launch as well as review a live example if a URL is provided. Another option would to test from the client/site side and provide a screenshot of the Nielsen call being made using a proxy tool (HTTPWatch, Fiddler, Charles, etc.) – prior to launch. The aim either way is to minimize missing impressions for your campaign, so it is in your best interest to provide for this testing if you can.<br />
<br />
'''What is considered to be an acceptable gap in reporting?'''<br />
<br />
In a perfect world, we’d like to see no gap in the numbers. We realize this is simply not possible – it is a factor of the Internet and having different counting methodologies, so we will aim for the lowest overall gap we can. Even with everything trafficked correctly; it is not uncommon to see gaps in the range of 5 to 10%, so we shoot for this range (if it’s lower than that, that’s great). If it’s greater than 10%, it usually indicates that there was something that was missed from being tagged or there’s an additional issue that requires further attention. When issues arise, we make all attempts to highlight and communicate the issue seen, to minimize the overall impact to the study, but are reliant on the client to ensure the issue is fixed. In a campaign where there are issues such as this, we try to keep the gap under 20% and will document any issues found. What are the capabilities for tagging video and video based ads?<br />
<br />
Our tag is not a specific limitation as it is one of the simplest things that can be served – a 1x1 image. That being said, much of the video implementation limitations are often dictated by the video vendors themselves. Where you can add our tag is dependent on the capabilities of these vendors. Some have the ability to place the tag in multiple locations in the video (i.e. beginning, middle, end – multiple tags will be needed to separate these out) and some simply place the pixel directly on the webpage, next to video being served. Further discussion may need to happen with the vendor, Nielsen and the client to determine the optimum implementation that meets the client's needs.<br />
</blockquote></div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DAR_Tag_Implementation_Guide&diff=5626DAR Tag Implementation Guide2022-02-02T19:03:19Z<p>LaMarHolmes: /* Unified ID */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|Digital Ad Ratings}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
<br />
== Introduction ==<br />
<br />
Nielsen Digital Ad Ratings is a measurement platform for online advertising campaigns. The platform provides a clear view of the true audience of a campaign, including '''Reach''', '''Frequency''', and '''GRP''' statistics by audience demographic group.<br />
<br />
The key innovation of the platform is the inclusion of demographic data from leading web publishers, including Facebook, to attach actual user demographics to ad impressions.<br />
<br />
The diagram below summarizes how the Nielsen tag measures the ad campaign:<br />
# Advertiser places ads on one or more websites<br />
#Website displays ad to a user<br />
#Nielsen tag counts impressions and controls redirect to the Data Enrichment Provider<br />
[[File:dar-image2.png|900px]]<br />
<br />
<br />
=== Support for Other Nielsen Ad Effectiveness Products ===<br />
<br />
The tag used for Nielsen Digital Ad Ratings is compatible for all Nielsen Ad Effectiveness products, including (but not limited to) Brand Effect Extended View, Response Effect, and Sales Effect.<br />
<br />
=== User Experience ===<br />
<br />
The tags described in this document are used only to measure audience exposure to advertisements; they do not launch a survey, and have no impact on the user experience. Typical response time for the tag is on par with industry standards and because the code executed is simple and fires after the ad loads, they are transparent to the user.<br />
<br />
For further information on survey-based products, or any other products, please contact your Client Services Manager.<br />
__TOC__<br />
== Available Tag Versions ==<br />
<br />
The Nielsen Digital Ad Ratings system offers 2 basic types of ad tags<br />
<br />
* '''IMAGE (1X1) Pixel'''<br />
This is the simplest version of the tag, generally for use by clients who cannot accept JavaScript format tags or have limited options for implementation. Itincludes encryption, but does not utilize referrer masking.<br />
<br />
* '''JavaScript Tag'''<br />
This is a more complex tag which includes encryption and masking of referrer site via a script call. This Tag may also be used to measure Viewability metrics.<br />
There may be additional functionality offered by this format in future releases as well.<br />
* '''Ad Networks''' This tag includes additional functionality to scrape the URL of the hosting website if associated to an ad network within the Nielsen system. Keep in mind URLs captured will only be used for “site adjustment factors” and not be included in any reporting<br />
<br />
<blockquote>'''NOTE''' - Both tag types support macros and are available in secure and non-secure formats. Please reach out to your Nielsen Technical Account Manager for additional information.</blockquote><br />
<br />
While the IMAGE pixels are easiest to implement, the JavaScript versions are recommended because they provide the highest level of confidentiality by masking the source of the ad from being viewable by Data Providers. Some situations may not afford use of JavaScript and in those cases, the pixel version will be recommended. Note that in many cases the referrer is cast as the ad server due to the nature of being served inside iframes, so the “masking” here is extraneous.<br />
<br />
=== Tag Examples ===<br />
<br />
<br><br />
'''IMAGE Pixel Tag''' (Static example)<br />
<syntaxhighlight lang="javascript"><br />
<img src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3&ca=cmpXXXX&cr=&pc=plcXXXX&r=[timestamp]"<br />
width="1" height="1" alt=""/><br />
</syntaxhighlight><br />
<br />
'''IMAGE Pixel Tag''' (Macro example)<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"><br />
</script><br />
</syntaxhighlight><br />
<br />
'''JavaScript Tag''' (Static example)<br />
<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3mr=1&ty=js&ca=cmpXXXX&cr=&pc=plcXXXX&r=[timestamp]"<br />
></script><br />
</syntaxhighlight><br />
<br />
'''JavaScript Tag''' (Macro example)<br />
<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"></<br />
script><br />
</syntaxhighlight><br />
<br><br />
<br />
The Nielsen Digital Ad Ratings system also features the ability to record Viewability information such as: How long an Ad has been visible on the screen, and what portion on the Ad. This is an additional feature that can be purchased from your Nielsen Client Services Representative.<br />
<br />
Viewability for display ads can ONLY be offered through the JavaScript tag. If you select this service, the following is an example of the tag that will be provided to you by the Nielsen Digital Implementation Team:<br />
<br />
'''JavaScript with Viewability for display ads:'''<br />
<syntaxhighlight lang="javascript"><br />
<script type="text/javascript"<br />
src="http://secure-gl.imrworldwide.com/cgi-bin/m?ci=entXXXX&am=1&mr=1&ty=js&at=view&rt=banner&ep=1&ca=%ebuy!&cr=%ecid!&pc=%epid!&r=[timestamp]"></<br />
script><br />
</syntaxhighlight><br />
<br />
<blockquote>The above tag is just examples and should not be placed in any live site or ad server. You will be provided with tags specifically designed for your media plan/campaign or be able to download tags after creation in CMI (Campaign Management Interface)</blockquote><br />
<br />
== Standard DAR Tag ==<br />
The DAR tag is available as a 1x1 pixel. The following pixel/tag parameters must be specified for all DAR tags, 1x1, regardless of implementation type: browser, mobile browser, mobile app or connected device.<br />
<br />
{| class="wikitable" <br />
|-<br />
! Tag Parameter<br />
! Description<br />
|-<br />
| CI<br />
| Client ID: the ID that is associated with the DAR account that processed tag data is associated with. Will always be hardcoded to a Nielsen generated value that comes from the Nielsen campaign management system<br />
|- style="background-color:#eff8ef;"<br />
| AM<br />
| Ad Server: an ad server participating on the campaign media-plan. This is an internal Nielsen generated value when the ad server is indicated on the campaign during setup<br />
|-<br />
| CA<br />
| Campaign Id: this is the ID associated with your DAR campaign. Unless you are creating and managing the Nielsen campaign via the DAR Tag API, then this parameter value will always be generated from the Nielsen campaign management system. Note: often maps to a media-plan I/O Id<br />
|- style="background-color:#eff8ef;"<br />
| CR<br />
| Creative Id: DAR does not currently report at the creative level; can be hard coded ad server id or associated with a macro expansion<br />
|-<br />
| PC<br />
| Placement Id: can be generated by the ad server via macro expansion or generated by the Nielsen campaign management system. Note: often maps to one of Ad Unit Id, Line Item Id or Video Ad Id<br />
|- style="background-color:#eff8ef;"<br />
| CE<br />
| Site Id: the Id that identifies a publisher site that the placement needs to be mapped to. Maps into the Nielsen MarketView database. Note: can be hardcoded to a pre-registered ad server site id in the Nielsen system or a macro expansion where more than one pre-existing site ids have been made known to Nielsen<br />
|-<br />
| R<br />
| Cachebuster (web): timestamp / random number. Generated by ad server<br />
|- style="background-color:#eff8ef;"<br />
| AT<br />
| Fixed value: “view”<br />
|-<br />
| RT<br />
| Fixed value: “banner”<br />
|- style="background-color:#eff8ef;"<br />
| ST<br />
| Fixed value: “image”<br />
|}<br />
<blockquote> Do not URL encode the values</blockquote><br />
<br />
== Additional Parameters ==<br />
In this section we describe the additional parameters that the DAR tag can support, specifically Hashed Email, UID2 values, along with Page URL and Bundle Identifier if available. Please work with your Nielsen Technical Account Manager on deciding which of the following parameters to append to the standard DAR tag. <br />
<br />
'''Web Browser DAR tag (cookie based persons identification)'''<br />
<br />
[https://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=nlsn_plc0001&ce=000&r=34245454 https://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=<siteid>&r=<timestamp>]<br />
<br />
'''Web Browser PLUS tag'''<br />
<br />
[http://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=554554_plc0001&ce=0000 http://secure-gl.imrworldwide.com/cgi-bin/m?ci=nlsnci535&am=3&at=view&rt=banner&st=image&ca=nlsn12452&cr=crtve&pc=<creativeid>_plc0001&ce=0000]&hem_sha256=<value>&uid2=<value>&uid_token=<value>&si=<value>c68=bndlid,com.tam.nielsen.com<br />
<br />
=== HEM Support (Hashed Email) ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"| Hashed Email <br />
| User’s email address that has been run through a hashing algorithm (e.g. SHA256, MD5, SHA1) </br> to create a unique 32-character hexadecimal string. If a client is unable to determine hashing type, they should pass using &hem_unknown parameter.<br />
|style="width: 20%"|<code>&hem_unknown</br>&hem_sha256</br>&hem_md5</br>&hem_md5</br>&hem_sha1</code><br />
|}<br />
<br />
<blockquote>Please use the parameter that matches your hashing algorithm.<br> For example, if you are using sha256 to encode the email address, then use <code>hem_sha256={encrypted_value_here}</code><br />
</blockquote><br />
Example:<br />
<syntaxhighlight lang="javascript"><br />
hem_sha256=tMmiiTI7IaAcPpQPFQ65uMVCWH8av9jw4cwf/F5HVRQ=<br />
</syntaxhighlight><br />
<br />
=== Unified ID ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"| Unified ID 2.0<br />
| An identifier based on a user’s verifiable PII (e.g. hashed email). UID2.0 was initially created by The Trade Desk (TTD)</br> and is now managed by Prebid. For more information on UID2.0 : https://github.com/UnifiedID2/uid2docs<br />
| &uid2<br />
|-<br />
| Unified ID 2.0 Token<br />
| Encrypted Unified ID 2.0<br />
| &uid_token<br />
|}<br />
<br />
Example:<br />
<syntaxhighlight lang="javascript"><br />
uid2=MTKVpUAzwYAPnHrtfE0wlINOMzhU7UUEjjVdCdRu63k=<br />
uid_token=AgAAAAPFR0zA5ogv/yaAPiUsAdZPsfqS8QlDSGxAB+rr8yekFs3AjLYVk5qqqiyV2XHbSuwzHmxSlLeQeKQI1mp015jsNnpX5/xGgXldcgVz+gFnyh3T8/3agMwRmyrhCxG4oH2C7<br />
fc48AQk2eotE7FW0ZDEYM8fD9ZxDaxFUC/OV3OuZA&<br />
</syntaxhighlight><br />
<br />
=== Page and Bundle ===<br />
{| class="wikitable" <br />
|- <br />
! NAME<br />
! DESCRIPTION<br />
! AVAILABLE TAG PARAMETERS<br />
|-<br />
| style="width: 15%"|Page URL<br />
| style="width: 65%"| Canonical URL of the content where the Ad creative is served. (e.g. https://example.com/news/tech/article.html) The parameter value has to be encoded with JavaScript’s encodeURIComponent() method or equivalent. <br />Example: si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
| &si<br />
|-<br />
| App Bundle ID<br />
| The app’s unique bundle ID (e.g. com.example.myapp). The ID can be used to look up the App in Apple’s App Store</br> or the Google Play Store. References:https://developer.android.com/studio/build/application-idhttps://developer.apple.com/documentation/appstoreconnectapi/bundle_ids<br />
| &c68=bndlid,<br />
|}<br />
<br />
Example:<br />
<syntaxhighlight><br />
si=https%3A%2F%2Fexample.com%2Fnews%2Ftech%2Farticle.html<br />
c68=bndlid,com.tam.nielsen.com<br />
</syntaxhighlight><br />
<br />
== Supported Creative Types ==<br />
<br />
For consistency, Nielsen recommends tagging as much of the campaign creative types as possible, including site-served elements. '''Note:''' Nielsen may need to review/test on a case-by-case basis.<br />
<br />
Nielsen Digital Ad Ratings supports banner ads, rich media and video units that are capable of being tagged with a 3rd party tracking pixel.<br />
<blockquote>Some examples of non-standard campaign items that may be tagged include:<br />
* microsite pages<br />
* site “skins’”<br />
* online mini-games<br />
* streaming video<br />
* pre-roll video banners<br />
</blockquote><br />
Most often, these items will need to be site served and our pixel will need to be provided to the site to implement directly.<br />
<blockquote>The following are items not tagged:<br />
* click command/text links<br />
* default/backup ads in a 3rd party ad server<br />
* static ‘logo’ creatives<br />
</blockquote><br />
<br />
Digital Ad Ratings Viewability Solution: All standard ad units listed under [http://www.iab.net/displayguidelines Universal Ad Package (UAP)] on are supported for Viewability.<br />
<br />
Placements and sites that cannot support JavaScript cannot support Viewability.<br />
<br />
'''‘Best Practices’ for Video Tags:''' Nielsen recommends all video tags be deployed as close to the beginning of the video stream as possible (post buffer).<br />
Placements delivering to Flash creative should have our tag implemented within the Flash code.<br />
<br />
== How the Tag Works ==<br />
<br />
The following describes the masked javascript version of the tag. <br><br />
For the non-masked pixel version of the tag, steps 5-8 would be collapsed to just 2 steps.<br />
<br />
[[File:image3-dar.png|right|500px]]<br />
# End-user uses her web browser to visit a website that contains an ad creative being measured by Nielsen.<br />
# Website sends web page back to end-user. (Web page contains HTML describing web content & ads)<br />
# End-user’s web browser requests the ad creative from Ad Server<br />
# Ad Server sends an iframe ad creative back to the end-user which contains the Nielsen measurement tag<br />
# End-user’s web browser makes a request to the Nielsen servers.<br />
## The tag’s HTTP request contains a campaign ID and placement, which is collected by Nielsen<br />
## The Nielsen system checks the user’s machine for an opt-out cookie – if one exists the process ends here<br />
## The Nielsen system checks to see if the campaign value in the tag was selected for Viewability. If so it downloads the Integral Ad Science tag to the end-user’s browser.<br />
# Nielsen server sends JavaScript code back to end-user’s web browser, including a 1x1 pixel.<br />
# End-user’s web browser executes JavaScript code and makes an iframe request to Nielsen server to enable the “referrer masking redirect”<br />
# Nielsen server sends an HTML message to the end-user’s web browser.<br />
# End-user’s web browser executes HTML and requests a 1x1 pixel from the Data Provider using Nielsen server information as the HTTP referrer – thus masking the Website’s information<br />
## The campaign ID and placement ID are passed through to Data Provider in an encrypted format<br />
# If Viewability is enabled the JavaScript will download a Javascript tag that calls the viewability vendor (either Nielsen or 3rd Party) to begin tracking inview metrics.<br />
# Data Provider responds with a 1x1 pixel. End process.<br />
<br />
== '''Share Your Delivered Impressions''' ==<br />
<br />
'''Why the Media Plan is Needed'''<br />
<br />
Knowing the delivered impressions also helps Nielsen run automated QA checks, for example triggering alerts when data does not appear for a placement on an expected date. This ensures overall quality, and reduces errors in the tagging process.<br />
<br />
It is the responsibility of the client to send Nielsen an impression delivery report, generally known as the “ad server report.” Nielsen can provide the client with a template with the inputs required to complete the quality checks. If the client does not send these reports, Nielsen will not be able to complete the quality checks. Below are instructions on how to send these reports to Nielsen.<br />
<br />
'''How to Share Your Delivered impressions'''<br />
<br />
Set up an automated daily report from your ad server containing Site Name, Site ID, Placement Name, Placement ID, and data date.<br />
<br />
A secondary method to share your media plan information is to grant Nielsen “Reporting access” to your campaign in the designated ad server (such as DCM). To do this, simply grant the login [http://mailto:clientreporting@nielsen.com clientreporting@nielsen.com] access. In doing so Nielsen can directly access your media plan information, which enables us to check for updates, and reconcile any<br /><br />
discrepancies.<br />
<br />
<blockquote>Please note that Nielsen is currently in discussions with several leading Ad Servers regarding direct integration between Nielsen and the ad server platforms. Once completed this could someday enable Nielsen to retrieve Media Plans on a completed automated basis.<br />
</blockquote><br />
<br />
== '''Apply the Tag''' ==<br />
=== '''Tag Generation''' ===<br />
<br />
Your Nielsen representative will walk you through the Campaign Management Interface so that you can download tags at will at any point in the campaign.<br />
<br />
Nielsen supports macro-based tag generation for several major ad servers. Nielsen’s Technical Account Manager (TAM) can assist you in leveraging macro-based tags.<br />
<br />
=== '''Tag Application''' ===<br />
<br />
Apply the tag according to the 3rd party tracking pixel specifications of your ad server. If additional guidance is needed, please consult with the Technical Account Manager (TAM) for more specific instructions or recommendations, if available.<br />
<br />
== Special Note for Video Tags ==<br />
Nielsen’s recommended “Best Practice” for tagging your video ads is to apply the Digital Ad Ratings tag as close to the beginning of the video as possible and after initiation of the ad stream, when the ad itself begins to appear on the user’s browser, closest to the opportunity to see. To ensure video content initiates during Digital Ad Ratings measurement, tags should always be placed post buffer. Recognizing that it’s not always possible to give the Nielsen pixel priority positioning, please be aware that the placement of the tag should be discussed with the publisher/advertiser counterparty so that both sides agree on the measurement approach.<br />
<br />
In accordance with MRC requirements, Clients must append “autop” parameter to detect click to play vs auto-play to their video tags. To detect auto-refresh (page refresh), “autof” parameter must be included (not limited to video tags).<br />
<syntaxhighlight lang=javascript><br />
<img src="http://secure-gl.imrworldwide.com/cgi-bim/m?ci=entXXXX&at=view&rt=banner&am=3&ca=cmpXXXX&cr=&pc=plcXXXX&<br />
autop=(value)&autof=(value)&r=[timestamp]" width="1" height="1" alt="" /><br />
</syntaxhighlight><br />
<br />
==== '''autop''' ====<br />
- A value of 1 will be passed when Auto-Play is detected. (e.g. autop=1)<br /><br />
- A value of 2 will be passed when Click-to-Play is detected. (e.g. autop=2)<br /><br />
- When no value or parameter is not present, impressions are labeled as Unknown Play.<br />
<br />
==== '''autof''' ====<br />
- A value of 1 will be passed when Auto-Refresh is detected. (e.g. autor=1)<br /><br />
- When no value or parameter is not present, impressions are labeled as Unknown Refresh.<br />
<br />
=== '''Special Note for Video Viewability Implementation:''' ===<br />
* Nielsen does not support any Flash based video players for viewability measurement.<br />
* The ad and tag must be in the same division (div tag) in order to track Viewability<br />
* Video:<br />
** VPAID compliant players<br />
** HTML5 Players (Flash not supported)<br />
** VPAID or mp4 creative<br />
** Video player must support VPAID and mp4<br />
<br />
=== '''Workflow and Tag Requirements for Nielsen Viewability with Qualified Ad Audience''' ===<br />
The following steps represent the tag/data flow between the publisher and Nielsen, through to final reporting.<br />
<blockquote> Please note that the assigned values for <code>CA, CI, AM, AM, PC and CR </code> in the example tags below are for illustrative purposes only to demonstrate the VW viewability state tag token. These values will need to be replaced with client specific data and/or macros specific to the ad serving situation.</blockquote><br />
<br />
# Ad creative exposed to the user<br /><br />
# Ad Server technology fires DAR tag on the publisher site<br /><br />
# Viewable state detected by Nielsen technology on publisher property; tag/signal sent to Nielsen collection system<br /><br />
# Nielsen collection system generates and executes the DAR tag with one of the following viewable states.<br />
# DAR data processing and reporting aggregates viewable impression states by campaign, placement and demographic attribution.<br />
<br />
==== '''Viewability Base URL &amp; Ping Paths''' ====<br />
<code> events.imrworldwide.com/VALUE?... </code><br />
<br />
==== '''Ping Path Values''' ====<br />
* /nmp - Measure Ping<br />
* /mp - Open Viewability Measure Ping<br />
* >/psp - Primary Standard Ping<br />
* /120sp - 120 Second Ping<br />
* /cp - Cadence Ping (used by SDK)<br />
* /fp - Final Ping<br />
* /er - Error Ping<br />
<br />
==== '''Nielsen DAR Tag/VPAID Query Strings''' ====<br />
'''Measure Ping'''<br />
<syntaxhighlight lang=html><br />
/nmp?impid=VALUE&amp;ca=VALUE&amp;ci=VALUE&amp;cr=VALUE&amp;ce=VALUE&amp;pc=VALUE&amp;am=VALUE&amp;<br />
cy=VALUE&amp;meas=VALUE&amp;ss=VALUE&amp;vp=VALUE&amp;as=VALUE&amp;al=VALUE<br />
</syntaxhighlight><br />
<br />
'''Primary Standard Ping'''<br />
<syntaxhighlight lang=html><br />
/psp?impid=VALUE&amp;vs=VALUE<br />
</syntaxhighlight><br />
<br />
'''120 Second Ping'''<br />
<syntaxhighlight lang=html><br />
/120sp?impid=VALUE&amp;vs=VALUE&amp;vts=VALUE&amp;ats=VALUE<br />
</syntaxhighlight><br />
'''Finish Ping'''<br />
<syntaxhighlight lang=html><br />
/fp?impid=VALUE&amp;vs=VALUE&amp;ss=VALUE&amp;vp=VALUE&amp;as=VALUE&amp;ar=VALUE&amp;vts=VALUE&amp;ats=VALUE<br />
</syntaxhighlight><br />
'''Error Ping'''<br />
<syntaxhighlight lang=html><br />
/er?impid=VALUE&amp;ca=VALUE&amp;ci=VALUE&amp;cr=VALUE&amp;ce=VALUE&amp;pc=VALUE&amp;am=VALUE&amp;ercd=VALUE<br />
</syntaxhighlight><br />
<br />
=== '''Workflow and Tag Requirements for 3rd Party Viewability''' ===<br />
The following steps represent the tag/data flow between publisher, Nielsen and the 3rd party viewability vendor (hereafter referred to as “vendor”), through to final reporting.<br />
<br />
<blockquote>Please note that the assigned values for CA, CI, AM, AM, PC and CR in the example tags below are for illustrative purposes only to demonstrate the VW viewability state tag token. These values will need to be replaced with client specific data and/or macros specific to the ad serving situation.</blockquote><br />
<br />
'''Requirements'''<br />
* Ad creative exposed to the user<br /><br />
* Vendor technology fires DAR tag on the publisher site<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/m?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignId]&amp;cr=[creativeId/macro]<br />
&amp;pc=[placementId/macro]&amp;r=[timestamp]<br />
</syntaxhighlight><br />
* Viewable state detected by vendor detection technology (i.e. vendor Javascript containertag) on publisher property; tag/signal sent to vendor collection system<br />
* Vendor collection system generates and executes the DAR tag with one of the following viewable state (see highlight) embedded<br />
<br />
==== '''onMeasureable''' ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignI d]&amp;cr=[creativeId/macro]&amp;pc=<br />
[amvalue]_[placementId/macro]&amp;vw=meas&amp;r=[timestamp]</syntaxhighlight><br />
<br />
==== '''onInViewMRC''' ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignId]&amp;cr=[creativeId/macro]<br />
&amp;pc=[amvalue]_[placementId/macro]&amp;vw=view&amp;r=[timestamp ]</syntaxhighlight><br />
==== '''onSuspicious''' ====<br />
<syntaxhighlight lang=html><br />
http://secure-gl.imrworldwide.com/cgi-bin/int?ci=[clientid]&amp;am=[AdserverId]&amp;at=view<br />
&amp;rt=banner&amp;st=image&amp;ca=[campaignI d]&amp;cr=[creativeId/macro]<br />
&amp;pc=[amvalue]_[placementId/macro]&amp;vw=susp&amp;r=[timestamp ]</syntaxhighlight><br />
<br />
* DAR data processing and reporting aggregates viewable impression states by campaign, placement and demographic attribution.<br />
<blockquote>'''Special Note for Nielsen Viewability with Qualified Ad Audience:''' Primary owner of campaign must provide assigned Technical Account Manager (TAM) VPAID tags per site/placement in order for VAST Wrapper to be delivered back to primary owner for implementation within their respective ad server, CMS, video serving platform, etc.<br />
</blockquote><br />
<br />
<blockquote>'''Special Note for Server Side Dynamic Ad Insertion:''' In cases where Server Side Dynamic Ad Insertion (SSDAI) is present, the Nielsen tag cannot execute unless the client side video player is coded to fire impression pixels when ads play. When this happens, all of the existing specifications for tag format, time, and criteria of execution (i.e. on play of ad) previously documented must be followed.<br />
</blockquote><br />
<br />
== '''QA Testing the Tag''' ==<br />
<br />
Nielsen’s Technical Account Manager (TAM) will coordinate a plan to test fire tags in advance of the campaign go-live date.<br />
<br />
In order to test the implementation of the Nielsen tag, at least one or two (more are<br /><br />
recommended) live URLs should be provided to the TAM. If a live page cannot be made available, at staging page or offline test page should be provided. The object of this is so that the TAM can see the Nielsen call being made live, exactly as it has been implemented, to verify all of the values expected – dynamic and static - are in the tag. A spot check of a couple of placements should be sufficient unless otherwise requested. In lieu of an actual test page, we may recommend you provide a screenshot of you testing the implementation from your end, showing the Nielsen call exactly as it is being called.<br />
<br />
Additionally, we will verify that the tags delivered have begun to receive data once the campaign actually goes live and will regularly (every 7-14 days, minimally) compare the Nielsen reporting to your 3rd party or publisher reporting to ensure we are capturing all of the data for all of the placements, as expected, and that the overall gap between your reporting and the Nielsen reporting is kept to a minimum.<br />
<br />
'''Detailed steps for confirming proper tag implementation'''<br />
* Open Chrome browser and enable “Developer Tools” (shortcuts: PC, “F12” - Mac, “Command+Option+I”)<br />
<blockquote>'''NOTE''' - Other browsers or debugging tools can also be used as an alternative (ie Firefox w/HttpFox extension, Fiddler, Charles, Wireshark, etc).</blockquote><br />
* Paste test page into browser URL field<br />
* Toggle to the “Network” tab<br />
** To isolate the DAR ping you can also input “imr” into the filter box<br />
[[File:image4-dar.png|900px]]<br />
<br />
<blockquote>'''TIP''' - If DAR tag does not display try refreshing the test page</blockquote><br />
=== '''If IMAGE tags were used''' ===<br />
'''Confirm call status is 302'''<br />
This ensures a redirect has been made to our Data Enrichment Provider<br />
[[File:image5-dar.png|600px]]<br />
<br />
'''Clicking on the call and navigating to the “Headers” tab will allow you to better evaluate tag construction'''<br />
[[File:image6-dar.png|500px]]<br />
<br />
'''The “Query String” section will disclose the tag parameter'''<br />
Confirm these values are displaying as expected<br />
<blockquote>'''NOTE''' - If ad server macro tokens are used, please ensure they are expanding properly<br />
</blockquote><br />
[[File:image7-dar.png|600px]]<br />
<br />
'''Optional - Review Data Enrichment Provider call'''<br />
his can be identified by searching for “brandlift”<br />
[[File:image8-dar.png|594px]]<br />
Call status should be 200<br />
<br />
<blockquote>'''NOTE''' - campaign tag parameters are encrypted when passed to Data Enrichment Provider</blockquote><br />
[[File:image9-dar.png|600px]]<br />
<br />
=== '''If JavaScript tags were used''' ===<br />
<br />
Steps are same as the above except for the following:<br />
* Two Nielsen (“imr”) calls will be made, both with status of 200<br />
** 1st - logs the impression on Nielsen servers<br />
** 2nd - initiates the call to our Data Enrichment Provider<br />
[[File:image10-dar.png|592px]]<br />
* 3rd (Optional) call is the same as above, review Data Enrichment Provider ping. This can be identified by searching for “brandlift”<br />
[[File:image11-dar.png|580px]]<br />
<br />
== '''Managing Campaign Updates''' ==<br />
<br />
As part of the campaign monitoring process, your Nielsen TAM will stay in close contact with you throughout the campaign, including scheduling periodic check-ins to check on the campaigns (approximately every 7-14 days, but could be more often, as needed). If you have provided reporting access to the campaign via your 3rd party or have scheduled a report to be delivered on a regular (weekly) basis, this can significantly expedite the monitoring of your campaign.<br />
<br />
If you have any questions regarding setting up the reporting to be delivered, fields that will need to be included, etc., please reach out to the TAM assigned to your campaign. If not providing direct access to reporting, please schedule reporting to be delivered on a weekly basis.<br />
</blockquote><br />
<br />
== '''Frequently Asked Questions''' ==<br />
<br />
'''What is a tag?'''<br />
<br />
For our purposes, a tag is an HTML code that is placed directly on a website or inside a 3rd party ad server to track exposure to an online advertisement. Adding the Nielsen tag to the<br /><br />
banners/videos/etc. is referred to in general as ‘tagging a campaign’.<br />
<br />
'''What is served by the Nielsen tag?'''<br />
<br />
The tag call is a simple 1x1 pixel image call. There is not a survey delivered at the time of ad call so this is not intrusive to the end user and should not adversely affect site page load times. <br />
<br />
'''What should be tagged?'''<br />
<br />
As much of the campaign that can be tagged, should be, for consistency. In most cases, we generally do not tag items such as: click command/text links, default/backup ads in a 3rd party ad server, or static ‘logo’ creatives. Whenever possible, we will request that you attempt to tag all other creative types, including site-served elements.<br />
<br />
'''Is there a way to differentiate between video “auto-play” and “click-to-play” impressions?'''<br />
<br />
The Nielsen pixel does not gather this type of granularity if the events are both sharing the same ad server placement ID. If it is desirable to compare the performance between these two events, our recommendation is to traffic these as individual placements within your ad serving<br /><br />
technology.<br />
<br />
'''What is the best way to add the Nielsen tag to my campaign?'''<br />
<br />
The Nielsen pixel should be called as close to the same time as the banner ad/creative element on which you would like to track exposure. Typically, this is handled by placing our tag inside a 3rd party ad server, such as Google’s DCM or a Rich Media vendor, such as PointRoll. However, if need be, our tag can be placed directly on a site page, immediately after the ad call in the same &lt;/div&gt; as the creative file. Further instruction can be provided on the kickoff call or we can work directly with trafficking contact(s) to get the tags in place.<br />
<br />
'''Do we need to use a 3rd party ad server to use the Nielsen tag?'''<br />
<br />
The short answer is no. In a lot of cases, we have provided a tag that can be implemented directly on a site. The benefit of placing our tag inside a 3rd party ad server is that we can provide a single tag (or minimal number of tags) that contain macros to simplify the tagging process.<br />
<br />
'''Is there anything that can’t be tagged?'''<br />
<br />
We may need to review/test on a case-by-case basis, but realistically most campaign elements can be tagged. Most often, these items will need to be site served and our pixel will need to be provided to the site to implement directly. Some examples of non-standard campaign items that have been tagged before include: microsite pages, site ‘skins’, online mini-games, streaming video, pre-roll video banners.<br />
<br />
'''The site has told us that they can accept only one pixel for the site served element. Can we append your tag to the end of ours?'''<br />
<br />
If you are serving a DCM 1x1 pixel to track these elements of your campaign, we have a method for placing our tag behind this call, to be served as a redirect. For other situations, we may need to discuss further and consider other options.<br />
<br />
'''I’m using more than one Nielsen study/product on this campaign. Will I need multiple/different tags for each?'''<br />
<br />
You should not need separate tags for each study. To keep the tagging process simple, we have designed our products so that a single tag can be used for multiple online studies, however, your TAM needs to be informed of all studies before launch so that they can be enabled.<br />
<br />
'''How much detail can be tracked with the Nielsen tag?'''<br />
<br />
Typically, we do an overall read for these studies, but we can segment the data by site, placement, ad size or creative, for example. If more granular data is desired, this should be discussed ahead of the campaign launch and planned for at the time of tag creation. ''We cannot segment the data if we have not tagged for it'' -- multiple tags will need to be created and implemented properly. Note that this can often be a time consuming process for the client trafficker and additional time should be allotted if this is needed. Lastly, keep in mind that exposure sample size may be a factor for segmenting the data at a more granular level.<br />
<br />
'''Why is it recommended to implement a timestamp or random number on the tag?''' This value will ensure that the tag call will not be cached on a user’s browser. It’s not absolutely necessary to implement for the tag to work, but without it you may see a larger gap between the impressions ran and what Nielsen captures. It is recommended to minimize this gap.<br />
<br />
'''For campaigns involving Facebook, what can’t be tagged on their site?'''<br />
<br />
Fan/Like pages are not allowed to be tagged, per Facebook. Additionally, Marketplace slots are not allowed to be tagged as these are user generated ads.<br />
<br />
'''What if it is not possible to provide a test or staging page before launch?'''<br />
<br />
While not ideal, we can view raw impression numbers on the day of the launch as well as review a live example if a URL is provided. Another option would to test from the client/site side and provide a screenshot of the Nielsen call being made using a proxy tool (HTTPWatch, Fiddler, Charles, etc.) – prior to launch. The aim either way is to minimize missing impressions for your campaign, so it is in your best interest to provide for this testing if you can.<br />
<br />
'''What is considered to be an acceptable gap in reporting?'''<br />
<br />
In a perfect world, we’d like to see no gap in the numbers. We realize this is simply not possible – it is a factor of the Internet and having different counting methodologies, so we will aim for the lowest overall gap we can. Even with everything trafficked correctly; it is not uncommon to see gaps in the range of 5 to 10%, so we shoot for this range (if it’s lower than that, that’s great). If it’s greater than 10%, it usually indicates that there was something that was missed from being tagged or there’s an additional issue that requires further attention. When issues arise, we make all attempts to highlight and communicate the issue seen, to minimize the overall impact to the study, but are reliant on the client to ensure the issue is fixed. In a campaign where there are issues such as this, we try to keep the gap under 20% and will document any issues found. What are the capabilities for tagging video and video based ads?<br />
<br />
Our tag is not a specific limitation as it is one of the simplest things that can be served – a 1x1 image. That being said, much of the video implementation limitations are often dictated by the video vendors themselves. Where you can add our tag is dependent on the capabilities of these vendors. Some have the ability to place the tag in multiple locations in the video (i.e. beginning, middle, end – multiple tags will be needed to separate these out) and some simply place the pixel directly on the webpage, next to video being served. Further discussion may need to happen with the vendor, Nielsen and the client to determine the optimum implementation that meets the client's needs.<br />
</blockquote></div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Mobile_Cloud_API&diff=5539DCR Video & Static Mobile Cloud API2021-12-10T18:07:09Z<p>LaMarHolmes: /* Example Request */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR & DTVR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
This guide shows you how to integrate the Nielsen Cloud API to enable Digital Content Ratings (DCR) measurement on your mobile apps.<br />
*For Roku Apps, please see [[DCR Video & Static Roku Cloud API]]<br />
*For OTT Devices, please see [[DCR Video & Static Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [UTC]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2" //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
|}<br />
<br />
On mobile devices you will need to pass the IDFA/Ad ID as part of the devId parameter. Please see the section below regarding Opt Out and the IDFA/Ad ID.<br />
<br />
===== Accessing the IDFA on iOS =====<br />
<br />
Accessing the ID For Advertisers (IDFA) uses OS level API calls. In order to do this, you must first import the following header file:<br />
<syntaxhighlight lang="objective-c">#import <AdSupport/ASIdentifierManager.h></syntaxhighlight><br />
<br />
Then to receive the IDFA as a NSString, use similar code to the following:<br />
<syntaxhighlight lang="objective-c">NSString *idfaString = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];</syntaxhighlight><br />
You can read more about ASIdentifierManager on Apple's [https://developer.apple.com/reference/adsupport/asidentifiermanager| developer website].<br />
<br />
===== Accessing the Ad ID on Android =====<br />
<br />
Accessing the Google Ad ID uses OS level API calls. In order to do this, you must first import Google Play Services. Then to receive the Ad ID, use the AdvertisingIdClient class as such:<br />
<syntaxhighlight lang="java">public static AdvertisingIdClient.Info getAdvertisingIdInfo (Context context)</syntaxhighlight><br />
<br />
You can read more about the AdvertisingIdClient class on Google's [https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient| developer website].<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || Yes<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || creditable position || playhead position in seconds or Unix timestamp (seconds since Jan-1-1970 UTC) for livestream || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp in milliseconds<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then discontinue sending playhead event updates.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Pause / Play<br />
*Network Loss (Wi-Fi / Airplane Mode / Cellular)<br />
*Wi-Fi OFF / ON<br />
*Call Interrupt (SIM or Third party Skype / Hangout call)<br />
*Alarm Interrupt<br />
*Content Buffering<br />
*Device Lock / Unlock (Video players only, not for Audio players)<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
*Channel / Station Change Scenario<br />
*Unplugging of headphone<br />
<br />
When playback is temporarily interrupted (e.g. pause, content buffering), the app needs to send the last known playhead position.<br />
<br />
*If an app is sent to background for more than 5 minutes, please create a new session ID. Otherwise, use the same session ID as before.<br />
*If loss of Internet occurs, please queue the API calls that would have been made. Once Internet connectivity is regained, please spool off the API calls in order of first generated (Note: if doing so, please use the UTC time in milliseconds)<br />
<br />
When playback is permanently interrupted, the app needs to send delete immediately.<br />
*If an app crashes, please create a new session ID. No delete call will be necessary as the previous session will timeout.<br />
<br />
Once playback resumes after delete occurs, 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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
var image = new Image()<br />
image.onerror = function() {<br />
// wait and send again<br />
}<br />
(new Image).src = sessionURL+encodeURIComponent(JSON.stringify(payload));<br />
</syntaxhighlight><br />
<br />
To ensure that the GET request does not receive a CORS issue, make sure to use the IMAGE request in conjunction with the content-type "text/plain" so CORS preflight is not triggered, causing the request to be rejected.<br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTPS Response Code ====<br />
<br />
Confirm request was completed by viewing HTTPS response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTPS Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
Your app must provide a means for the user to Opt-Out, or Opt-In to Nielsen Measurement. The Opt-Out requirement can be fulfilled by creating an Opt-Out/Opt-In button, toggle switch, or slider within the app "Settings", or "About" section to allow the user selection. If you have the ability to render text within the Opt-Out screen, it is recommended to add the Privacy Information included below.<br />
<br />
[[File:Nielsen Opt-Out.png|link=]]<br />
<br />
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). <br />
<br />
*In addition, you will need to ensure that the devId field is a blank value if a user has elected to Opt-Out<br />
<br />
*If the device offers "Limit Ad Tracking" or "Opt-Out" device settings, you must set uoo=true, and also ensure that the devId is set to a blank value if the user elects to enable this setting.<br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement (Recommended Default Setting) || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"devId": "7be25cf9-8c40-5cc2-871e-19bf41940288",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"devId": "", //devId must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Privacy Information Template To Include In Opt-Out Screen =====<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out, or opt into Nielsen measurement please make the appropriate selection within the app. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.<br />
</blockquote><br />
'''''Disclosure Template'''''<br />
<br />
Additionally, you must update the App description information from the App Distribution Store with the Nielsen Measurement disclosure below:<br />
<blockquote><br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see http://www.nielsen.com/digitalprivacy for more information.<br />
</blockquote><br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTPS Response ====<br />
*Make sure that each of the Cloud API Get requests are received by the Nielsen Cloud API properly through use of the HTTPS Response Code outputs enabled in console.<br />
<br />
==== Opt-Out ====<br />
*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.<br />
*Test that the devId field is populated with a blank value if a user has elected to Opt-Out. For example: "devId": "",<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Roku_Cloud_API&diff=5538DCR Video & Static Roku Cloud API2021-12-10T18:06:25Z<p>LaMarHolmes: /* Example Request */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR & DTVR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
This guide shows you how to integrate the Nielsen Cloud API to enable Digital Content Ratings (DCR) measurement on your Roku Apps.<br />
*For other OTT Apps, please see [[DCR Video & Static Cloud API]]<br />
*For Mobile Apps, please see [[DCR Video & Static Mobile Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
During testing, all calls should be pointed to the testing endpoint. Once your application has been certified, the URL should be updated to point to the Cloud API production endpoint.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [UTC]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
The session ID must be passed with every request and must remain consistent throughout each individual session.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"apn": "AppName",<br />
"encdata": "encdata=v1.key.RokuAES256CBC00.iv3x2EV0BpHH9AbZK%2FnBWWRhZbj7pD%3D...",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| encdata || Nielsen - Roku ID for Advertisers || N-RIDA Payload || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
| Example || Example || Example || Yes<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Encdata (N-RIDA): Nielsen - Roku Identifier for Advertisers =====<br />
The N-RIDA (Nielsen-Roku ID for Advertisers) is a proprietary advertising identifier that ties back to an individual Roku device, and allows Nielsen to attribute audience metrics. The N-RIDA is provided by Roku, and is pulled through the Roku <code>[https://sdkdocs.roku.com/display/sdkdoc/Integrating+the+Roku+Advertising+Framework#IntegratingtheRokuAdvertisingFramework-getNielsenContentData()asString AdIface.GetNielsenContentData()]</code> API.<br />
<br />
The N-RIDA payload should be requested once per user session and populated in the <code>"encdata"</code> Nielsen key within the <code>"devInfo"</code> payload. Each Cloud API request throughout a user session should include the same N-RIDA payload. The N-RIDA should be established when a user launches the app, and it should be maintained until the user exits. A new N-RIDA payload should be requested when the user re-enters the app.<br />
<br />
'''Prerequisites For Using The AdIface.GetNielsenContentData() Roku API'''<br />
<br />
* Roku Ad Framework (RAF) must be implemented:<br />
** <code>bs_libs_required=roku_ads_lib</code> must be included in the Roku manifest file.<br />
** <code>Library "Roku_Ads.brs"</code> should be the first entry in your Roku main.brs file.<br />
** <code>adIface = Roku_Ads()</code> allows you to access the Roku Ad Framework interface and must be called before utilizing RAF API's such as <code>AdIface.GetNielsenContentData()</code><br />
* For additional details for integrating the Roku Ad Framework (RAF) please refer to the link provided below:<br />
** https://sdkdocs.roku.com/display/sdkdoc/Integrating+the+Roku+Advertising+Framework<br />
<br />
===== Request N-RIDA for the devInfo Payload encdata parameter using AdIface.GetNielsenContentData() =====<br />
<br />
'''Example Code For Configuring Encdata'''<br />
<syntaxhighlight lang="java">// create a variable as a placeholder for the N-RIDA payload<br />
n_Rida=AdIface.GetNielsenContentData()<br />
<br />
// populate the encdata key in devInfo with the AdIface.GetNielsenContentData() retrun<br />
"devInfo": {<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"encdata": "n_Rida", //insert the AdIface.GetNielsenContentData() return within encdata<br />
"uoo": "false"<br />
}</syntaxhighlight><br />
<br />
<blockquote>'''Note''': When pulled and populated into the encdata key, the <code>AdIface.GetNielsenContentData()</code> return will be formatted similarly to the example below, and will include "encdata=" within the return along with the N-RIDA key.</blockquote><br />
<syntaxhighlight lang="json">"encdata":"encdata=v1.key.RokuAES256CBC00.iv.HSh88AM%2BG%2Fx57TZ%2BW5j5Fw%3D%3D..."</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || No<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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. Upon resuming content, continue to pass playhead position every 10 seconds starting at the playhead position in which content was paused. 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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || creditable position || playhead position in seconds or Unix Time for live stream || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===Example Image Request===<br />
<br />
In order to execute Cloud API calls, image requests will need to be established for each event.<br />
<br />
===Playhead Image Request Example Code===<br />
<br />
<syntaxhighlight lang="javascript"><br />
playheadRequest = CreateObject("roUrlTransfer")<br />
sendUrl = sessionUrl+playheadRequest.Escape(playheadPayload)<br />
playheadRequest.SetUrl(sendUrl)<br />
xport=CreateObject("RoMessagePort")<br />
playheadRequest.setport(xport)<br />
aa3 = {}<br />
aa3["Connection"] = "keep-alive"<br />
aa3["Content-type"] = "image/gif"<br />
playheadRequest.SetHeaders(aa3)<br />
playheadRequest.setRequest("GET")<br />
</syntaxhighlight><br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then stop passing the playhead position until content is resumed. Once content resumes, continue to pass playhead position every 10 seconds starting at the playhead position in which content was paused.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
When playback is interrupted, the app needs to send delete immediately.<br />
<br />
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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
sendUrl = sessionUrl.Escape(payload)<br />
</syntaxhighlight><br />
<br />
To ensure that the GET request does not receive a CORS issue, make sure to use the IMAGE request in conjunction with the content-type "text/plain" so CORS preflight is not triggered, causing the request to be rejected.<br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
print "Playhead Event " + sendUrl<br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
print "Event Payload "+ playheadPayload + modSeq%.tostr()<br />
</syntaxhighlight><br />
<br />
==== HTTPS Response Code ====<br />
<br />
Confirm request was completed by viewing HTTPS response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
httpCode = GetResponseCode()<br />
print "Response Code " +httpCode.tostr()<br />
</syntaxhighlight><br />
<br />
You can reference the HTTPS Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
<br />
Your app must provide a means for the user to Opt-Out, or Opt-In to Nielsen Measurement. This can be implemented in two steps:<br />
<br />
==== Step 1: Nielsen Privacy Policy & Roku Channel Disclosure ====<br />
<br />
In your application, you must display the Nielsen privacy policy, which instructs users on how to opt out and opt in to Nielsen measurements. This text is usually displayed in an application's "Settings" or "About" screens.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out, or opt into Nielsen measurement please choose the appropriate "Limit Ad Tracking" setting on your device. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit https://www.nielsen.com/digitalprivacy<br />
</blockquote><br />
<br />
In addition, on your Roku Channel description, you should add the following disclosure:<br />
<br />
<blockquote><br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see https://www.nielsen.com/digitalprivacy for more information.<br />
</blockquote><br />
<br />
==== Step 2: Use "Limit Ad Tracking" setting to set User Opt Out ====<br />
<br />
Depending on the user's selection for the "Limit Ad Tracking" device setting, you should set the Cloud API <code>"uoo"</code> parameter accordingly. Roku provides an API called [https://sdkdocs.roku.com/display/sdkdoc/ifDeviceInfo#ifDeviceInfo-IsAdIdTrackingDisabled()asBoolean IsAdIdTrackingDisabled()] to check the user's limit ad tracking setting.<br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
The <code>"uoo"</code> parameter is located in the <code>"devInfo"</code> JSON object, which will be sent in every Cloud API event (playhead, complete, & delete).<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"encdata": "", //Encdata must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
Your application should check the Limit Ad Tracking setting on each app start, and/or periodically, to ensure the user's ad tracking selection is reflected in the Nielsen opt-out setting in your app.<br />
<br />
*In addition, you will need to ensure that the encdata field is populated with a blank value if a user has elected to Opt-Out.<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*When content is paused, send the current position and then stop passing playhead position until content resumes. Once content resumes, continue passing playhead position every 10 seconds starting at the position in which content was paused.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent.<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded.<br />
<br />
==== HTTPS Response ====<br />
*Make sure that each of the Cloud API Get requests are received by the Nielsen Cloud API properly through use of the HTTPS Response Code outputs enabled in console.<br />
<br />
==== Opt-Out ====<br />
*Test the "uoo" key gets populated accurately for both Opt-In and Opt-Out selections based on the device's "Limit Ad Tracking" setting.<br />
*Test that the encdata field is populated with a blank value if a user has elected to Opt-Out. For Example: "encdata": "",<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging.</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Cloud_API&diff=5537DCR Video & Static Cloud API2021-12-10T18:05:21Z<p>LaMarHolmes: /* Example Request */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
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.<br />
*For Roku Apps, please see [[DCR Video & Static Roku Cloud API]]<br />
*For Mobile Apps, please see [[DCR Video & Static Mobile Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [Unix time in ms]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2" //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || No<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || playhead position in seconds or Unix time in seconds || <code>"300"</code> || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp in milliseconds<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
* Playheads should be sent in seconds only, not milliseconds<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then discontinue sending playhead event updates.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
When playback is interrupted, the app needs to send delete immediately.<br />
<br />
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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
var image = new Image()<br />
image.onerror = function() {<br />
// wait and send again<br />
}<br />
(new Image).src = sessionURL+encodeURIComponent(JSON.stringify(payload));<br />
</syntaxhighlight><br />
<br />
To ensure that the GET request does not receive a CORS issue, make sure to use the IMAGE request in conjunction with the content-type "text/plain" so CORS preflight is not triggered, causing the request to be rejected.<br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTPS Response Code ====<br />
<br />
Confirm request was completed by viewing HTTPS response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTPS Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
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.<br />
<br />
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.<br />
<br />
[[File:Nielsen Opt-Out.png|link=]]<br />
<br />
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). <br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement (Recommended Default Setting) || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "7be25cf9-8c40-5cc2-871e-19bf41940288",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "", //devId must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Privacy Information Template To Include In Opt-Out Screen =====<br />
<br />
<br />
Additionally, all applications must display the Nielsen privacy policy within their application, typically in the Settings/About screen of your application. The Nielsen privacy policy text is listed below.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out or opt in to Nielsen measurement, please toggle your "Limit Ad Tracking" (or similar setting) on your device, or make the appropriate selection within the application's settings. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.<br />
<br />
</blockquote><br />
'''''Disclosure Template'''''<br />
<br />
Additionally, you must update the App description information from the App Distribution Store with the Nielsen Measurement disclosure below:<br />
<br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see http://www.nielsen.com/digitalprivacy for more information.<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit, if the platform has the necessary exit callback events.<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTPS Response ====<br />
*Make sure that each of the Cloud API Get requests are received by the Nielsen Cloud API properly through use of the HTTPS Response Code outputs enabled in console.<br />
<br />
==== Opt-Out ====<br />
*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.<br />
*Test that the devId field is populated with a blank value if a user has elected to Opt-Out. For example: "devId": "",<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Roku_Cloud_API&diff=5519DCR Video & Static Roku Cloud API2021-12-02T21:40:56Z<p>LaMarHolmes: /* Content Metadata */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR & DTVR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
This guide shows you how to integrate the Nielsen Cloud API to enable Digital Content Ratings (DCR) measurement on your Roku Apps.<br />
*For other OTT Apps, please see [[DCR Video & Static Cloud API]]<br />
*For Mobile Apps, please see [[DCR Video & Static Mobile Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
During testing, all calls should be pointed to the testing endpoint. Once your application has been certified, the URL should be updated to point to the Cloud API production endpoint.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [UTC]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
The session ID must be passed with every request and must remain consistent throughout each individual session.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"apn": "AppName",<br />
"encdata": "encdata=v1.key.RokuAES256CBC00.iv3x2EV0BpHH9AbZK%2FnBWWRhZbj7pD%3D...",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| encdata || Nielsen - Roku ID for Advertisers || N-RIDA Payload || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
| Example || Example || Example || Yes<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Encdata (N-RIDA): Nielsen - Roku Identifier for Advertisers =====<br />
The N-RIDA (Nielsen-Roku ID for Advertisers) is a proprietary advertising identifier that ties back to an individual Roku device, and allows Nielsen to attribute audience metrics. The N-RIDA is provided by Roku, and is pulled through the Roku <code>[https://sdkdocs.roku.com/display/sdkdoc/Integrating+the+Roku+Advertising+Framework#IntegratingtheRokuAdvertisingFramework-getNielsenContentData()asString AdIface.GetNielsenContentData()]</code> API.<br />
<br />
The N-RIDA payload should be requested once per user session and populated in the <code>"encdata"</code> Nielsen key within the <code>"devInfo"</code> payload. Each Cloud API request throughout a user session should include the same N-RIDA payload. The N-RIDA should be established when a user launches the app, and it should be maintained until the user exits. A new N-RIDA payload should be requested when the user re-enters the app.<br />
<br />
'''Prerequisites For Using The AdIface.GetNielsenContentData() Roku API'''<br />
<br />
* Roku Ad Framework (RAF) must be implemented:<br />
** <code>bs_libs_required=roku_ads_lib</code> must be included in the Roku manifest file.<br />
** <code>Library "Roku_Ads.brs"</code> should be the first entry in your Roku main.brs file.<br />
** <code>adIface = Roku_Ads()</code> allows you to access the Roku Ad Framework interface and must be called before utilizing RAF API's such as <code>AdIface.GetNielsenContentData()</code><br />
* For additional details for integrating the Roku Ad Framework (RAF) please refer to the link provided below:<br />
** https://sdkdocs.roku.com/display/sdkdoc/Integrating+the+Roku+Advertising+Framework<br />
<br />
===== Request N-RIDA for the devInfo Payload encdata parameter using AdIface.GetNielsenContentData() =====<br />
<br />
'''Example Code For Configuring Encdata'''<br />
<syntaxhighlight lang="java">// create a variable as a placeholder for the N-RIDA payload<br />
n_Rida=AdIface.GetNielsenContentData()<br />
<br />
// populate the encdata key in devInfo with the AdIface.GetNielsenContentData() retrun<br />
"devInfo": {<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"encdata": "n_Rida", //insert the AdIface.GetNielsenContentData() return within encdata<br />
"uoo": "false"<br />
}</syntaxhighlight><br />
<br />
<blockquote>'''Note''': When pulled and populated into the encdata key, the <code>AdIface.GetNielsenContentData()</code> return will be formatted similarly to the example below, and will include "encdata=" within the return along with the N-RIDA key.</blockquote><br />
<syntaxhighlight lang="json">"encdata":"encdata=v1.key.RokuAES256CBC00.iv.HSh88AM%2BG%2Fx57TZ%2BW5j5Fw%3D%3D..."</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || No<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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. Upon resuming content, continue to pass playhead position every 10 seconds starting at the playhead position in which content was paused. 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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || creditable position || playhead position in seconds or Unix Time for live stream || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===Example Image Request===<br />
<br />
In order to execute Cloud API calls, image requests will need to be established for each event.<br />
<br />
===Playhead Image Request Example Code===<br />
<br />
<syntaxhighlight lang="javascript"><br />
playheadRequest = CreateObject("roUrlTransfer")<br />
sendUrl = sessionUrl+playheadRequest.Escape(playheadPayload)<br />
playheadRequest.SetUrl(sendUrl)<br />
xport=CreateObject("RoMessagePort")<br />
playheadRequest.setport(xport)<br />
aa3 = {}<br />
aa3["Connection"] = "keep-alive"<br />
aa3["Content-type"] = "image/gif"<br />
playheadRequest.SetHeaders(aa3)<br />
playheadRequest.setRequest("GET")<br />
</syntaxhighlight><br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then stop passing the playhead position until content is resumed. Once content resumes, continue to pass playhead position every 10 seconds starting at the playhead position in which content was paused.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
When playback is interrupted, the app needs to send delete immediately.<br />
<br />
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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
sendUrl = sessionUrl.Escape(payload)<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
print "Playhead Event " + sendUrl<br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
print "Event Payload "+ playheadPayload + modSeq%.tostr()<br />
</syntaxhighlight><br />
<br />
==== HTTPS Response Code ====<br />
<br />
Confirm request was completed by viewing HTTPS response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
httpCode = GetResponseCode()<br />
print "Response Code " +httpCode.tostr()<br />
</syntaxhighlight><br />
<br />
You can reference the HTTPS Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
<br />
Your app must provide a means for the user to Opt-Out, or Opt-In to Nielsen Measurement. This can be implemented in two steps:<br />
<br />
==== Step 1: Nielsen Privacy Policy & Roku Channel Disclosure ====<br />
<br />
In your application, you must display the Nielsen privacy policy, which instructs users on how to opt out and opt in to Nielsen measurements. This text is usually displayed in an application's "Settings" or "About" screens.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out, or opt into Nielsen measurement please choose the appropriate "Limit Ad Tracking" setting on your device. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit https://www.nielsen.com/digitalprivacy<br />
</blockquote><br />
<br />
In addition, on your Roku Channel description, you should add the following disclosure:<br />
<br />
<blockquote><br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see https://www.nielsen.com/digitalprivacy for more information.<br />
</blockquote><br />
<br />
==== Step 2: Use "Limit Ad Tracking" setting to set User Opt Out ====<br />
<br />
Depending on the user's selection for the "Limit Ad Tracking" device setting, you should set the Cloud API <code>"uoo"</code> parameter accordingly. Roku provides an API called [https://sdkdocs.roku.com/display/sdkdoc/ifDeviceInfo#ifDeviceInfo-IsAdIdTrackingDisabled()asBoolean IsAdIdTrackingDisabled()] to check the user's limit ad tracking setting.<br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
The <code>"uoo"</code> parameter is located in the <code>"devInfo"</code> JSON object, which will be sent in every Cloud API event (playhead, complete, & delete).<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"encdata": "", //Encdata must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
Your application should check the Limit Ad Tracking setting on each app start, and/or periodically, to ensure the user's ad tracking selection is reflected in the Nielsen opt-out setting in your app.<br />
<br />
*In addition, you will need to ensure that the encdata field is populated with a blank value if a user has elected to Opt-Out.<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*When content is paused, send the current position and then stop passing playhead position until content resumes. Once content resumes, continue passing playhead position every 10 seconds starting at the position in which content was paused.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent.<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded.<br />
<br />
==== HTTPS Response ====<br />
*Make sure that each of the Cloud API Get requests are received by the Nielsen Cloud API properly through use of the HTTPS Response Code outputs enabled in console.<br />
<br />
==== Opt-Out ====<br />
*Test the "uoo" key gets populated accurately for both Opt-In and Opt-Out selections based on the device's "Limit Ad Tracking" setting.<br />
*Test that the encdata field is populated with a blank value if a user has elected to Opt-Out. For Example: "encdata": "",<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging.</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Cloud_API&diff=5518DCR Video & Static Cloud API2021-12-02T21:40:32Z<p>LaMarHolmes: /* Content Metadata */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
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.<br />
*For Roku Apps, please see [[DCR Video & Static Roku Cloud API]]<br />
*For Mobile Apps, please see [[DCR Video & Static Mobile Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [Unix time in ms]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2" //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || No<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || playhead position in seconds or Unix time in seconds || <code>"300"</code> || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp in milliseconds<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
* Playheads should be sent in seconds only, not milliseconds<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then discontinue sending playhead event updates.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
When playback is interrupted, the app needs to send delete immediately.<br />
<br />
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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
var image = new Image()<br />
image.onerror = function() {<br />
// wait and send again<br />
}<br />
(new Image).src = sessionURL+encodeURIComponent(JSON.stringify(payload));<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTPS Response Code ====<br />
<br />
Confirm request was completed by viewing HTTPS response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTPS Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
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.<br />
<br />
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.<br />
<br />
[[File:Nielsen Opt-Out.png|link=]]<br />
<br />
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). <br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement (Recommended Default Setting) || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "7be25cf9-8c40-5cc2-871e-19bf41940288",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "", //devId must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Privacy Information Template To Include In Opt-Out Screen =====<br />
<br />
<br />
Additionally, all applications must display the Nielsen privacy policy within their application, typically in the Settings/About screen of your application. The Nielsen privacy policy text is listed below.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out or opt in to Nielsen measurement, please toggle your "Limit Ad Tracking" (or similar setting) on your device, or make the appropriate selection within the application's settings. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.<br />
<br />
</blockquote><br />
'''''Disclosure Template'''''<br />
<br />
Additionally, you must update the App description information from the App Distribution Store with the Nielsen Measurement disclosure below:<br />
<br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see http://www.nielsen.com/digitalprivacy for more information.<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit, if the platform has the necessary exit callback events.<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTPS Response ====<br />
*Make sure that each of the Cloud API Get requests are received by the Nielsen Cloud API properly through use of the HTTPS Response Code outputs enabled in console.<br />
<br />
==== Opt-Out ====<br />
*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.<br />
*Test that the devId field is populated with a blank value if a user has elected to Opt-Out. For example: "devId": "",<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_CTV_Device_SDK_Privacy&diff=5504DCR Video & Static CTV Device SDK Privacy2021-11-10T18:07:05Z<p>LaMarHolmes: /* Privacy and Opt-Out on SDK integrated OTT Devices */</p>
<hr />
<div>== Privacy and Opt-Out on SDK integrated CTV Devices ==<br />
<br />
CTV devices that are able to have the Mobile App SDK integrated (FireTV, AndroidTV, AppleTV etc.) should make sure to display a WebView element whose loadUrl is set to the value obtained from optOutURL. If using the Global iOS SDK, this optOutURL informs the user how to deactivate/activate “App Tracking/Limit Ad Tracking”. If using the Global Android SDK, this optOutURL informs the user how to deactivate/activate “Out of Ads Personalization”.<br />
<br />
In addition, the following text must be included in your app store description.<br />
<blockquote>"Please note: This app features Nielsen’s proprietary measurement software which contributes to market research, like Nielsen’s TV Ratings. Please see https://sites.nielsen.com/priv/browser/us/en/optout.html for more information"</blockquote><br />
<br />
If displaying a WebView element is not possible then a client can utilize the CTV Opt Out verbiage used by clients who have implemented Cloud API :<br />
<br />
{{OTT_Opt_Out_Verbiage}}</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=Template:Android_Privacy_and_Opt-Out&diff=5503Template:Android Privacy and Opt-Out2021-11-10T18:04:41Z<p>LaMarHolmes: /* Webview Element */</p>
<hr />
<div>== Privacy and Opt-Out ==<br />
There are currently 3 flavors of the Nielsen SDK:<br />
# '''[[#Global_Android_SDK_Opt-out|Global Android SDK Opt-out]]''' - managed by ''Opt out of Ads Personalization'' setting on device ('''preferred approach''').<br />
# '''[[#Global_Android_SDK_No_Ad_Framework_Optout|Global Android SDK No Ad Framework Optout]]''' - Direct call to SDK. Can be used without Google Play Services or when using the noAd version of the SDK.<br />
# '''[[#Global_Android_SDK_No_ID_Optout_.28Kids_Category.29|Global Android SDK No ID Optout]]''' - Direct call to SDK. Should be used for Kids Category.<br />
<br />
=== Global Android SDK Opt-out ===<br />
''OS-level Opt-out'' method available on Nielsen Android when the [https://developers.google.com/android/guides/setup Google Play services APIs] have been setup in your project.<br />
<br />
The Nielsen SDK automatically leverages the Android's '''Opt out of Ads Personalization''' setting. The user is opted out of demographic measurement if the OS-level '''Opt out of Ads Personalization''' setting is ''enabled''. As a publisher, you cannot override this setting.<br />
<br />
==== Webview Element ====<br />
It is a requirement to display a WebView element whose loadUrl is set to the value obtained from optOutURL.<br />
If using the Global Android SDK, this optOutURL informs the user how to deactivate/activate “Out of Ads Personalization”.<br />
<br />
In addition, The following text must be included in your app store description.<br />
<blockquote>"'''Please note: This app features Nielsen’s proprietary measurement software which contributes to market research, like Nielsen’s TV Ratings. Please see https://nielsen.com/digitalprivacy/ for more information'''"</blockquote><br />
<br />
If you are implementing on Android TV or Fire TV here are your Opt Out verbiage options : https://engineeringportal.nielsen.com/docs/DCR_Video_%26_Static_CTV_Device_SDK_Privacy<br />
<br />
==== Retrieve current Opt-Out preference ====<br />
Whether the user is opted out via OS-level Opt-out or via App-level Opt-out, the current Opt-Out status as detected by the SDK is available via the [[getOptOutStatus()]] property in the Nielsen Android SDK API. <code>appSdk.getOptOutStatus()</code><br />
<br />
=== Global Android SDK No Ad Framework Optout ===<br />
The ''No Ad Framework Optout'' can be used when the host application does not leverage Google Play Services such as when using the noAd version or the NoID version.<br />
<blockquote><br />
Nielsen Android SDK 5.1.1.18 and above will check for ''OS-level opt-out'' first, if available. The user will be opted out if indicated at the OS-level '''OR''' the App-level.</blockquote><br />
<br />
==== The No Ad Framework Optout method works as follows: ====<br />
* Get the current Nielsen opt-out URL via [[userOptOutURLString()]]<br />
* Display a WebView element whose loadUrl is set to the value obtained from [[userOptOutURLString()]]<br />
* Detect if the WebView URL changes to a special URL that indicates Opt-in, or Opt-out and close the WebView<br />
** Opt-out if the WebView URL = <code>nielsenappsdk://1</code><br />
** Opt-in if the WebView URL = <code>nielsenappsdk://0</code><br />
* Pass the detected URL to the [[userOptOut()]] function<br />
** Example: <syntaxhighlight lang=java>appSdk.userOptOut("nielsenappsdk://1"); // User opt-out</syntaxhighlight><br />
<br />
=== Global Android SDK No ID Optout (Kids_Category) ===<br />
If you are building an app that will be listed in the Kids Category:<br />
# Ensure that you are using the NoID version of the Nielsen SDK Framework.<br />
# Immediately following the initialization of the Nielsen SDK ensure you call the userOptOut API with Opt out selection: <br />
<syntaxhighlight lang=java>appSdk.userOptOut("nielsenappsdk://1"); // User opt-out</syntaxhighlight><br />
<br />
== OptOut Example Code ==<br />
Below you will find some sample code for the:<br />
* [[#Global OptOut Example|Global Android SDK]] - managed by Opt out of Ads Personalization setting on device '''(preferred approach)'''.<br />
* [[#No_Ad_Framework_Optout_Sample_Code|Global Android noAd Framework]] - Use if Google Play APIs are unavailable or running noAd version.<br />
* It is currently not required to display an OptOut page for the NoID/Kids Build of the SDK.<br />
===<span id="Global OptOut Example"></span>Global OptOut Example ===<br />
The below code is an AndroidX example of displaying the Nielsen Privacy page to the user. Please see the next section if using the No Ad Framework build<br />
<syntaxhighlight lang="java"><br />
public class OptOutActivity extends AppCompatActivity implements IAppNotifier {<br />
<br />
WebView webView;<br />
AppSdk appSdk;<br />
<br />
@Override<br />
public void onCreate(@Nullable Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_optout);<br />
webView = (WebView) findViewById(R.id.webView);<br />
webView.getSettings().setJavaScriptEnabled(true);<br />
<br />
webView.setWebViewClient(new WebViewClient() {<br />
@SuppressWarnings("deprecation")<br />
@Override<br />
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {<br />
Toast.makeText(OptOutActivity.this, description, Toast.LENGTH_SHORT).show();<br />
}<br />
@TargetApi(android.os.Build.VERSION_CODES.M)<br />
@Override<br />
public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) {<br />
// Redirect to deprecated method, so you can use it in all SDK versions<br />
onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString());<br />
}<br />
<br />
});<br />
String url = appSdk.userOptOutURLString(); // Request Optout URL from NielsenSDK<br />
webView.loadUrl(url); //Display to the user in a Webview<br />
}<br />
@Override<br />
public void onBackPressed() {<br />
super.onBackPressed();<br />
mSdkInterface.getSDK(appSdk);<br />
}<br />
@Override<br />
protected void onDestroy() {<br />
super.onDestroy();<br />
if (appSdk != null)<br />
{<br />
appSdk.close();<br />
appSdk = null;<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
<br><br />
<br />
===<span id="No Ad Framework Optout Sample Code"></span>No Ad Framework Optout Sample Code ===<br />
The below code is an AndroidX example of displaying the Nielsen Privacy page to the user with the No Ad Framework SDK Build.<br />
<syntaxhighlight lang="java"><br />
public class OptOutActivity extends AppCompatActivity implements IAppNotifier {<br />
<br />
WebView webView;<br />
AppSdk appSdk;<br />
<br />
@Override<br />
public void onCreate(@Nullable Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_optout);<br />
webView = (WebView) findViewById(R.id.webView);<br />
webView.getSettings().setJavaScriptEnabled(true);<br />
<br />
webView.setWebViewClient(new WebViewClient() {<br />
@SuppressWarnings("deprecation")<br />
@Override<br />
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {<br />
Toast.makeText(OptOutActivity.this, description, Toast.LENGTH_SHORT).show();<br />
}<br />
@TargetApi(android.os.Build.VERSION_CODES.M)<br />
@Override<br />
public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) {<br />
// Redirect to deprecated method, so you can use it in all SDK versions<br />
onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString());<br />
}<br />
<br />
<br />
@Override<br />
public boolean shouldOverrideUrlLoading(WebView view, String url) {<br />
<br />
if(url.contains("nielsen")){<br />
// If url value = "nielsenappsdk://1 it means the user selected Opt Out<br />
// If url value = "nielsenappsdk://0" it means the user selected Opt-In<br />
appSdk.userOptOut(url);<br />
}<br />
return true;<br />
}<br />
<br />
});<br />
String url = appSdk.userOptOutURLString(); // Request Optout URL from NielsenSDK<br />
webView.loadUrl(url); //Display to the user in a Webview<br />
}<br />
@Override<br />
public void onBackPressed() {<br />
super.onBackPressed();<br />
mSdkInterface.getSDK(appSdk);<br />
}<br />
@Override<br />
protected void onDestroy() {<br />
super.onDestroy();<br />
if (appSdk != null)<br />
{<br />
appSdk.close();<br />
appSdk = null;<br />
}<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Retrieve current Opt-Out preference ==<br />
Whether the user is opted out via OS-level Opt-out or via App-level Opt-out, the current Opt-Out status as detected by the SDK is available via the [[getOptOutStatus()]] property in the Nielsen Android SDK API. <code>appSdk.getOptOutStatus()</code><br />
<br />
== Going Live ==<br />
Following Nielsen testing, you will need to:<br />
<br />
# '''Disable Debug Logging''': Disable logging by deleting <code>{nol_devDebug: 'DEBUG'}</code> from initialization call.<br />
# '''Notify Nielsen''': Once you are ready to go live, let us know so we can enable you for reporting. We will not be able to collect or report data prior to receiving notification from you.</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=Template:iOS_Privacy_and_Opt-Out&diff=5502Template:iOS Privacy and Opt-Out2021-11-10T18:03:13Z<p>LaMarHolmes: /* Webview Element */</p>
<hr />
<div>== Privacy and Opt-Out ==<br />
<br />
There are currently 3 flavors of the Nielsen SDK. Please check the "Implementation" section for a comparison of the three flavors. Implementing opt-out for the three flavors are different:<br />
# '''[[#Global_iOS_SDK_Opt-out|Global iOS SDK Opt-out]]''' - managed by ''AppTracking'' or ''Limit Ad Tracking'' setting on device.<br />
# '''[[#Global_iOS_SDK_No_Ad_Framework_Opt-out|Global iOS SDK No Ad Framework Opt-out]]''' - Direct call to SDK. Can be used without the Ad Framework.<br />
# '''[[#Global_iOS_SDK_No_ID_Opt-out|Global iOS SDK No ID Opt-out]]''' - Direct call to SDK. Should be used for Kids Category.<br />
__NOTOC__<br />
=== Global iOS SDK Opt-out ===<br />
''OS-level Opt-out'' method available on Nielsen iOS <br />
<br />
The Nielsen SDK automatically leverages the iOS's '''Limit Ad Tracking''' or '''AppTracking''' setting. <br />
* If the User's device is running < iOS 13.x, the Nielsen SDK will check the status of '''Limit Ad Tracking'''.<br />
* iOS14 modifies the way Apple manages the collection of a User's Opt-In status through '''AppTracking'''. Starting with Version 8.x+, the Nielsen App SDK will check the iOS version during initialization. If the device is running iOS12 or iOS13, the Limit Ad Tracking setting is requested. If iOS14.x +, then AppTracking is utilized.<br />
==== Webview Element ====<br />
It is a requirement to display a WebView element whose loadUrl is set to the value obtained from optOutURL.<br />
If using the Global iOS SDK, this optOutURL informs the user how to deactivate/activate “App Tracking/Limit Ad Tracking”.<br />
<br />
In addition, the following text must be included in your app store description.<br />
<blockquote>"Please note: This app features Nielsen’s proprietary measurement software which contributes to market research, like Nielsen’s TV Ratings. Please see https://sites.nielsen.com/priv/browser/us/en/optout.html for more information"</blockquote><br />
<br />
If you are implementing on AppleTV here are your Opt Out verbiage options : https://engineeringportal.nielsen.com/docs/DCR_Video_%26_Static_CTV_Device_SDK_Privacy<br />
<br />
==== Sample Code for Global Build ====<br />
===== Swift =====<br />
<syntaxhighlight lang="swift"><br />
import UIKit<br />
import WebKit<br />
import NielsenAppApi<br />
<br />
class OptOutVC: UIViewController, NielsenAppApiDelegate, WKNavigationDelegate {<br />
var nielsenApi : NielsenAppApi!<br />
var webView: WKWebView!<br />
<br />
override func loadView() {<br />
webView = WKWebView()<br />
webView.navigationDelegate = self<br />
view = webView<br />
}<br />
<br />
override func viewDidLoad() {<br />
super.viewDidLoad()<br />
<br />
if let appApi = self.nielsenApi {<br />
//Getting the optPut URL from SDK<br />
if let url = URL(string: appApi.optOutURL) {<br />
webView.load(URLRequest(url: url))<br />
webView.allowsBackForwardNavigationGestures = true<br />
}}}<br />
<br />
func closeOptOutView() {<br />
self.dismiss(animated: true, completion: nil)<br />
}}<br />
</syntaxhighlight><br />
<br />
===== Objective-C =====<br />
<syntaxhighlight lang="objective-c"><br />
<br />
#import "OptOutVC.h"<br />
#import "NielsenInit.h"<br />
#import <NielsenAppApi/NielsenAppApi.h><br />
<br />
@interface OptOutVC ()<br />
<br />
@property (weak, nonatomic) IBOutlet UIWebView *webView;<br />
@end<br />
<br />
@implementation OptOutVC<br />
<br />
- (void)viewDidLoad {<br />
[super viewDidLoad];<br />
<br />
- (void)viewDidLoad {<br />
[super viewDidLoad];<br />
//Getting the optPut URL from eventTracker<br />
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL<br />
URLWithString:self.nielsenApi.optOutURL]]];<br />
}}<br />
<br />
<br />
</syntaxhighlight><br />
<br />
=== Global iOS SDK No Ad Framework Opt-out ===<br />
The ''User Choice'' method can be used without the Ad Framework, or in situations where the publisher does not wish to use the [https://developer.apple.com/documentation/apptrackingtransparency App Tracking Transparency Framework]. As this flavor of the Nielsen SDK does not use the Ad Framework, so it is necessary to display an Optout Page to the user and capture their selection.<br />
<br />
Similar to the Global iOS SDK Flavor, it is a requirement to display a WebView element whose loadUrl is set to the<br />
value obtained from optOutURL. This is a special URL that indicates Opt-in, or Opt-out and close the WebView. '''The steps are as follows:'''<br />
<br />
* Get the Nielsen opt-out URL via [[optOutURL]]<br />
* Display a WebView element whose loadUrl is set to the value obtained from [[optOutURL]]<br />
* Detect if the WebView URL changes to a special URL that indicates Opt-in, or Opt-out and close the WebView<br />
** Opt-out if the WebView URL = <code>nielsenappsdk://1</code><br />
** Opt-in if the WebView URL = <code>nielsenappsdk://0</code><br />
* Pass the detected URL to the [[userOptOut]] function<br />
** Example: <syntaxhighlight lang=swift>NielsenAppApi?.userOptOut("nielsenappsdk://1"); // User opt-out</syntaxhighlight><br />
<br />
==== Sample code for No Ad Framework Build ====<br />
===== Swift =====<br />
<syntaxhighlight lang="swift"><br />
import UIKit<br />
import WebKit<br />
import NielsenAppApi<br />
<br />
class OptOutVC: UIViewController, NielsenAppApiDelegate, WKNavigationDelegate {<br />
var nielsenApi : NielsenAppApi!<br />
var webView: WKWebView!<br />
<br />
override func loadView() {<br />
webView = WKWebView()<br />
webView.navigationDelegate = self<br />
view = webView<br />
}<br />
<br />
override func viewDidLoad() {<br />
super.viewDidLoad()<br />
<br />
if let appApi = self.nielsenApi {<br />
//Getting the optPut URL from SDK<br />
if let url = URL(string: appApi.optOutURL) {<br />
webView.load(URLRequest(url: url))<br />
webView.allowsBackForwardNavigationGestures = true<br />
}}}<br />
<br />
func closeOptOutView() {<br />
self.dismiss(animated: true, completion: nil)<br />
}<br />
<br />
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: <br />
@escaping (WKNavigationActionPolicy) -> Void) {<br />
print(navigationAction.request.url?.absoluteString as Any) //For debugging to check what is being passed from webpage.<br />
if navigationAction.request.url?.absoluteString == "nielsen://close" {<br />
closeOptOutView()<br />
decisionHandler(.cancel)<br />
} else {<br />
if let url = navigationAction.request.url?.absoluteString, url.hasPrefix("nielsen") {<br />
nielsenApi?.userOptOut(url). //either nielsenappsdk://1 or nielsenappsdk://0<br />
decisionHandler(.cancel)<br />
} else {<br />
if navigationAction.navigationType == .linkActivated {<br />
if let url = navigationAction.request.url?.absoluteString, url.hasSuffix("#") {<br />
decisionHandler(.allow)<br />
} else {<br />
decisionHandler(.cancel)<br />
webView.load(navigationAction.request)<br />
}<br />
} else {<br />
decisionHandler(.allow)<br />
}}}}<br />
<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
===== Objective-C =====<br />
<syntaxhighlight lang="objective-c"><br />
<br />
#import "OptOutVC.h"<br />
#import "NielsenInit.h"<br />
#import <NielsenAppApi/NielsenAppApi.h><br />
<br />
@interface OptOutVC ()<br />
<br />
@property (weak, nonatomic) IBOutlet UIWebView *webView;<br />
@end<br />
<br />
@implementation OptOutVC<br />
<br />
- (void)viewDidLoad {<br />
[super viewDidLoad];<br />
<br />
- (void)viewDidLoad {<br />
[super viewDidLoad];<br />
//Getting the optPut URL from eventTracker<br />
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL<br />
URLWithString:self.nielsenApi.optOutURL]]];<br />
}<br />
<br />
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction<br />
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler<br />
{<br />
if ([navigationAction.request.URL.absoluteString isEqualToString:kNielsenWebClose])<br />
{ [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];<br />
decisionHandler(WKNavigationActionPolicyCancel); <br />
} else {<br />
if ([navigationAction.request.URL.absoluteString hasPrefix:@"nielsen"])<br />
{[self.nielsenAppApi userOptOut:navigationAction.request.URL.absoluteString];<br />
decisionHandler(WKNavigationActionPolicyCancel); <br />
} else {<br />
if (navigationAction.navigationType == WKNavigationTypeLinkActivated) <br />
{ if ([navigationAction.request.URL.absoluteString hasSuffix:@"#"]) <br />
{decisionHandler(WKNavigationActionPolicyAllow);<br />
} else {<br />
decisionHandler(WKNavigationActionPolicyCancel);<br />
[webView loadRequest:[NSURLRequest requestWithURL:navigationAction.request.URL]];<br />
}} else {<br />
decisionHandler(WKNavigationActionPolicyAllow);<br />
}}}<br />
}<br />
<br />
</syntaxhighlight><br />
<br />
<br />
=== Global iOS SDK No ID Opt-out ===<br />
If you are building an app that will be listed in the Kids Category:<br />
# Ensure that you are using the [https://nielsendownloads-green.digitalengsdk.com/digital/Nielsen-iOS-App-SDK-GlobalNoId_latest.zip NoID version] of the Nielsen SDK Framework.<br />
# Immediately following the initialization of the Nielsen SDK ensure you call the userOptOut API with Opt out selection: <br />
<syntaxhighlight lang=swift>NielsenAppApi?.userOptOut("nielsenappsdk://1"); // User opt-out</syntaxhighlight><br />
<br />
== Retrieve current Opt-Out preference ==<br />
Whether the user is opted out via OS-level Opt-out or via User Choice Opt-out, the current Opt-Out status as detected by the SDK is available via the [[optOutStatus]] property in the Nielsen SDK API<br />
<syntaxhighlight lang="objective-c"><br />
@property (readonly) BOOL optOutStatus<br />
</syntaxhighlight></div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_CTV_Device_SDK_Privacy&diff=5501DCR Video & Static CTV Device SDK Privacy2021-11-10T17:02:03Z<p>LaMarHolmes: LaMarHolmes moved page OTTDevice SDK Privacy to DCR Video & Static CTV Device SDK Privacy without leaving a redirect: Changing page location</p>
<hr />
<div>== Privacy and Opt-Out on SDK integrated OTT Devices ==<br />
<br />
OTT devices that are able to have the Mobile App SDK integrated (FireTV, AndroidTV, AppleTV etc.) should make sure to display a WebView element whose loadUrl is set to the value obtained from optOutURL. If using the Global iOS SDK, this optOutURL informs the user how to deactivate/activate “App Tracking/Limit Ad Tracking”. If using the Global Android SDK, this optOutURL informs the user how to deactivate/activate “Out of Ads Personalization”.<br />
<br />
In addition, the following text must be included in your app store description.<br />
<blockquote>"Please note: This app features Nielsen’s proprietary measurement software which contributes to market research, like Nielsen’s TV Ratings. Please see https://sites.nielsen.com/priv/browser/us/en/optout.html for more information"</blockquote><br />
<br />
If displaying a WebView element is not possible then a client can utilize the OTT Opt Out verbiage used by clients who have implemented Cloud API :<br />
<br />
{{OTT_Opt_Out_Verbiage}}</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_CTV_Device_SDK_Privacy&diff=5493DCR Video & Static CTV Device SDK Privacy2021-11-08T18:54:13Z<p>LaMarHolmes: </p>
<hr />
<div>== Privacy and Opt-Out on SDK integrated OTT Devices ==<br />
<br />
OTT devices that are able to have the Mobile App SDK integrated (FireTV, AndroidTV, AppleTV etc.) should make sure to display a WebView element whose loadUrl is set to the value obtained from optOutURL. If using the Global iOS SDK, this optOutURL informs the user how to deactivate/activate “App Tracking/Limit Ad Tracking”. If using the Global Android SDK, this optOutURL informs the user how to deactivate/activate “Out of Ads Personalization”.<br />
<br />
In addition, the following text must be included in your app store description.<br />
<blockquote>"Please note: This app features Nielsen’s proprietary measurement software which contributes to market research, like Nielsen’s TV Ratings. Please see https://sites.nielsen.com/priv/browser/us/en/optout.html for more information"</blockquote><br />
<br />
If displaying a WebView element is not possible then a client can utilize the OTT Opt Out verbiage used by clients who have implemented Cloud API :<br />
<br />
{{OTT_Opt_Out_Verbiage}}</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_CTV_Device_SDK_Privacy&diff=5492DCR Video & Static CTV Device SDK Privacy2021-11-08T18:48:24Z<p>LaMarHolmes: Created page with "== Privacy and Opt-Out on SDK integrated OTT Devices == OTT devices that are able to have the Mobile App SDK integrated (FireTV, AndroidTV, AppleTV etc.) should make sure to..."</p>
<hr />
<div>== Privacy and Opt-Out on SDK integrated OTT Devices ==<br />
<br />
OTT devices that are able to have the Mobile App SDK integrated (FireTV, AndroidTV, AppleTV etc.) should make sure to display a WebView element whose loadUrl is set to the value obtained from optOutURL. If using the Global iOS SDK, this optOutURL informs the user how to deactivate/activate “App Tracking/Limit Ad Tracking”. If using the Global Android SDK, this optOutURL informs the user how to deactivate/activate “Out of Ads Personalization”.<br />
<br />
In addition, the following text must be included in your app store description.<br />
<blockquote>"Please note: This app features Nielsen’s proprietary measurement software which contributes to market research, like Nielsen’s TV Ratings. Please see https://sites.nielsen.com/priv/browser/us/en/optout.html for more information"</blockquote><br />
<br />
If a displaying a WebView element is not possible then a client can utilize the OTT Opt Out verbiage used by clients who have implemented Cloud API :<br />
<br />
{{OTT_Opt_Out_Verbiage}}</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=Template:OTT_Opt_Out_Verbiage&diff=5491Template:OTT Opt Out Verbiage2021-11-08T16:47:28Z<p>LaMarHolmes: Created page with "===== Privacy Information Template To Include In Opt-Out Screen ===== Additionally, all applications must display the Nielsen privacy policy within their application, typica..."</p>
<hr />
<div>===== Privacy Information Template To Include In Opt-Out Screen =====<br />
<br />
<br />
Additionally, all applications must display the Nielsen privacy policy within their application, typically in the Settings/About screen of your application. The Nielsen privacy policy text is listed below.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out or opt in to Nielsen measurement, please toggle your "Limit Ad Tracking" (or similar setting) on your device, or make the appropriate selection within the application's settings. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.<br />
<br />
</blockquote><br />
'''''Disclosure Template'''''<br />
<br />
Additionally, you must update the App description information from the App Distribution Store with the Nielsen Measurement disclosure below:<br />
<br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see http://www.nielsen.com/digitalprivacy for more information.</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Static_Android_SDK&diff=5462DCR Static Android SDK2021-10-20T18:12:06Z<p>LaMarHolmes: </p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|US DCR & DTVR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
=== Prerequisites ===<br />
To start using the App SDK, the following items are required:<br />
{| class="wikitable"<br />
|-<br />
! style="width: 30px;" |<br />
! style="width: 15%;" | Item<br />
! Description<br />
! Source<br />
|-<br />
|| ☑ || '''App ID (appid)''' || Unique ID assigned to the player/site and configured by product. || Contact Nielsen<br />
|-<br />
|| ☑ || '''sfcode''' || Environment that the SDK must point to || Contact Nielsen<br />
|-<br />
|| ☑ || '''Nielsen SDK''' || Includes SDK libraries and '''sample implementation'''; ''See [[Android SDK Release Notes]]'' || [[Special:Downloads|Download]]<br />
|}<br />
If you do not have any of these pre-requisites or if you have any questions, please contact our SDK sales support team.<br />
Refer to [[Digital Measurement Onboarding]] guide for more information on how to get a Nielsen App SDK and appid.<br />
<br />
=== Import Library ===<br />
Refer to [[Android SDK API Reference#Setting Up Development Environment|Android SDK API Reference - Setting Up Development Environment]] for information on importing libraries.<br />
* The latest version of App SDK allows instantiating multiple instances of App SDK object and can be used simultaneously without any issues.<br />
<blockquote>Note: The latest version of App SDK contains only appsdk.jar file and does not feature any native shared libraries like libAppSdk.so.</blockquote><br />
<blockquote>Note: The integrator should always tag the landing page on the app.</blockquote><br />
<br />
=== Initialize SDK ===<br />
Initialize App SDK as soon as the application is launched. Refer to [[iOS SDK API Reference#Initialization|Initalization]] for details on initializing an AppSDK object and the parameters required.<br />
<br />
=== Configure API calls - play ===<br />
For static <App Measurement> content, play API is not required.<br />
<br />
==== Configure API calls - loadMetadata ====<br />
Use [[loadMetadata]] to pass 'content' [[Digital Measurement Metadata]]. The CMS data must be passed as a JSON object.<br />
<syntaxhighlight lang="java"> loadMetadata(JSONObject jsonMetadata);</syntaxhighlight><br />
Refer to [[Digital Measurement Metadata]] for the list of parameters to be passed in the JSON object.<br />
<blockquote>Note: The [[loadMetadata]] call must have ("type": "static"). </blockquote><br />
<br />
=== Configure API calls - playheadPosition ===<br />
For static <App Measurement> content, no playhead has to be supplied to the SDK.<br />
<br />
==== stop ====<br />
For static <App Measurement> content, stop API is not required.<br />
<br />
==== API Call sequence ====<br />
Call [[loadMetadata]] with JSON metadata as below.<br />
<syntaxhighlight lang="java"> new JSONObject()<br />
.put("type", "static")<br />
.put("section", "siteSection")<br />
.put("assetid", "vid345-67483")<br />
.put("segA", "segmentA")<br />
.put("segB", "segmentB")<br />
.put("segC","segmentC")<br />
}</syntaxhighlight><br />
<br />
[[File:Sdk_dataflow.jpg]]<br />
<br />
=== Configure Metadata ===<br />
Map the Nielsen keys to variables so that the content metadata is dynamically updated.<br />
<br />
The Nielsen reserved keys are:<br />
{| class="wikitable"<br />
|-<br />
! Key !! Description !! Data Type !! Value !! Required?<br />
|-<br />
| type || asset type || fixed || <code>'static'</code> || Yes<br />
|-<br />
| assetid || Unique ID for each article || dynamic || custom <br>(no [[Special Characters]]) || No<br />
|-<br />
| 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 || Yes<br />
|-<br />
| segA || custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) || dynamic || custom || No<br />
|-<br />
| segB || custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) || dynamic || custom || No<br />
|-<br />
| segC || custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) || dynamic || custom || No<br />
|}<br />
<br />
The values passed through the Nielsen keys will determine the breakouts that are seen in reporting. The custom segments (A, B & C) will roll into the sub-brand. To not use custom segments A, B and C, do not pass any value in these keys.<br />
<br />
'''Aggregation Limits'''<br />
There are limits on the number of unique values that can be aggregated on in reporting. The specific limitations by key are:<br />
{| class="wikitable"<br />
|-<br />
! Key !! Aggregation Limit<br />
|-<br />
| section || maximum of 25 unique values (section <= 25)<br />
|-<br />
| segA || Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25)<br />
|-<br />
| segB || Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25)<br />
|-<br />
| segC || Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25)<br />
|}<br />
<br />
== Handling Foreground and Background states ==<br />
There are a few approaches to managing the Foreground and Background states of an app available to use for state measurement.<br />
* Utilizing the Androidx LifeCycleObserver (The recommended approach starting sdk version 7.1.0.0+)<br />
* Utilizing the [[DCR_Video_Android_SDK#The_SdkBgFgDetectionUtility_class|SdkBgFgDetectionUtility]] class<br />
* Adding a tag to the Manifest XML<br />
* Manual Management<br />
=== The LifeCycleObserver ===<br />
AndroidX replaces the original support library APIs with packages in the androidx namespace, and Android Studio 3.2 and higher provides an automated migration tool. (Select '''Refactor> Migrate to AndroidX''' from the menu bar.)<br />
<br />
Starting with version 7.1.0, with AndroidX support, an additional utility is provided in the AppSDK - application background/foreground state detection by the AppSdk leveraging the Android Architecture component "LifeCycleObserver".<br />
<br />
The AppSdk is now capable of detecting the application UI visibility state transitions between background and foreground, without forcing the applications to register for AppSdk's AppSdkApplication class, which is responsible for handling the detection of application background/foreground state transitions at present.<br />
<br />
<blockquote>Please note, that if you already have an app designed that utilizes the depreciated SdkBgFgDetectionUtility Class, the AppSDK will ignore any calls to these methods if it can utilize the LifeCycleObserver. LifeCycleObserver based auto detection will take precedence. </blockquote><br />
==== Adding the AndroidX dependency ====<br />
In order to make use of the app background/foreground state transition auto detection feature of AndroidX AppSdk, the app gradle file needs the androidx dependency. The AppSdk API calls - <code>appInForeground()</code> and <code>appInBackground()</code> will still be respected by AppSdk by executing the old AppSdk flow of handling "app in foreground" and "app in background" states as is.<br />
<br />
==== Using the LifeCycle Extension ====<br />
The following androidx dependency is required in the app gradle file:<br />
<syntaxhighlight lang="java"><br />
implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"<br />
</syntaxhighlight><br />
<br />
<blockquote><br />
If you would like to take advantage of this auto detection feature of AppSdk at the very initial stage (e.g. splash screen or at of app launch time), before the AppSdk is initialized, can do so by calling the following newly introduced AppSdk public api, passing the application context :<br />
<syntaxhighlight lang="java"><br />
public static void registerLifeCycleObserver(Context applicationContext)<br />
</syntaxhighlight><br />
</blockquote><br />
<br />
==== Log messages for the new auto detection ====<br />
<br />
When the AppSdk app successfully registers for the LifeCycleObserver : <code>Registered LifeCycleObserver for App Background/Foreground auto-detection</code><br />
<br />
* When the app enters the foreground state :<code>App is in foreground, auto detected by AppSDK</code><br />
* When the app enters the background state :<code>App is in background, auto detected by AppSDK</code><br />
* If the client app doesn't have the "androidx" gradle dependency and AppSdk fails to register LifeCycleObserver :<code>AndroidX LifecycleObserver can not be observed. Please use androidx dependency to activate SDK auto-detection of app background/foreground state.</code><br />
* When the appInForeground() is explicitly called while LifeCycleObserver auto detection is active :<code>Ignoring the appInBackground() call, as the App Background/Foreground auto-detection is active. The current state is - foreground</code><br />
* When the appInBackground() is explicitly called while LifeCycleObserver auto detection is active :<code>Ignoring the appInBackground() call, as the App Background/Foreground auto-detection is active. The current state is - background</code><br />
<br />
=== The SdkBgFgDetectionUtility class ===<br />
Foreground/Background state measurement is a requirement of Nielsen AppSDK implementation which is especially crucial for static measurement. It may be implemented in multiple ways for Android. This includes<br />
* Enable the Nielsen SDK to measure background/foreground state by makingthe relevant update to the AndroidManifest.<br />
* Integrate Nielsen’s SdkBgFgDetectionUtility class within your Custom Application Class.<br />
* Custom implementation of the required methods within your application.<br />
<br />
==== ForeGround/Background Measurement via AndroidManifest ====<br />
The simplest way to measure the app background/foreground state is to add the following application tag to the Manifest XML. Integrating this into the Manifest XML will enable the SDK to measure app state directly. This approach is supported for Android 4.0 and up only; it requires that the application class is not in use for some other purpose.<br />
<syntaxhighlight lang="java"><br />
<application android:name="com.nielsen.app.sdk.AppSdkApplication"><br />
</syntaxhighlight><br />
<br />
==== Using the Android SdkBgFbDetectionUtility Class ====<br />
For developers who are already using the application class, it is recommended that background/foreground state is implemented using the [https://engineeringportal.nielsen.com/docs/Android_Background_Foreground SdkBgFgDetectionUtility class]. The [https://engineeringportal.nielsen.com/docs/Android_Background_Foreground SdkBgFgDetectionUtility class] is compatible with Android 4+ and has been made available to Nielsen clients. (You will need to copy/paste the code provided into a file).<br />
<br />
==== Manual Background/ForeGround State Management ====<br />
In cases where the developer is not able to use the AndroidManifest.xml solution nor the Nielsen provided [https://engineeringportal.nielsen.com/docs/Android_Background_Foreground SdkBgFgDetectionUtility class] the developer will need to manually identify the change of state through the application and call the respective API (appInForeground() or appInBackground()) to inform the SDK regarding the change of state from background to foreground or foreground to background.<br />
<br />
The SDK is informed about app state using the below methods.<br />
<syntaxhighlight lang="java"><br />
AppLaunchMeasurementManager.appInForeground(getApplicationContext());<br />
AppLaunchMeasurementManager.appInBackground(getApplicationContext());<br />
</syntaxhighlight><br />
Within the lifecycle of individual activities, onResume() and onPause() are best suited to providing indication of the app state.<br />
<br />
<br />
Correct measurement of the foreground/background state is crucial to Static App measurement within Nielsen Digital Content Ratings (DCR).<br />
<br />
{{Template:Android_Privacy_and_Opt-Out}}<br />
<br />
== Pre-Certification Checklists ==<br />
After the application is ready to be sent for Nielsen Certification, please go through the Pre-Certification Checklist and ensure the app behaves as expected, before submitting to Nielsen.<br />
<br />
== Testing an Implementation - App ==<br />
See [[Digital Measurement Testing]].</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Cloud_API&diff=5159DCR Video & Static Cloud API2021-08-17T16:28:45Z<p>LaMarHolmes: /* HTTP Response */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
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.<br />
*For Roku Apps, please see [[DCR Video & Static Roku Cloud API]]<br />
*For Mobile Apps, please see [[DCR Video & Static Mobile Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [Unix time in ms]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2" //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || Yes<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || playhead position in seconds or Unix time in seconds || <code>"300"</code> || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp in milliseconds<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
* Playheads should be sent in seconds only, not milliseconds<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then discontinue sending playhead event updates.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
When playback is interrupted, the app needs to send delete immediately.<br />
<br />
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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
var image = new Image()<br />
image.onerror = function() {<br />
// wait and send again<br />
}<br />
(new Image).src = sessionURL+encodeURIComponent(JSON.stringify(payload));<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTPS Response Code ====<br />
<br />
Confirm request was completed by viewing HTTPS response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTPS Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
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.<br />
<br />
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.<br />
<br />
[[File:Nielsen Opt-Out.png|link=]]<br />
<br />
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). <br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement (Recommended Default Setting) || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "7be25cf9-8c40-5cc2-871e-19bf41940288",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "", //devId must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Privacy Information Template To Include In Opt-Out Screen =====<br />
<br />
<br />
Additionally, all applications must display the Nielsen privacy policy within their application, typically in the Settings/About screen of your application. The Nielsen privacy policy text is listed below.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out or opt in to Nielsen measurement, please toggle your "Limit Ad Tracking" (or similar setting) on your device, or make the appropriate selection within the application's settings. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.<br />
<br />
</blockquote><br />
'''''Disclosure Template'''''<br />
<br />
Additionally, you must update the App description information from the App Distribution Store with the Nielsen Measurement disclosure below:<br />
<br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see http://www.nielsen.com/digitalprivacy for more information.<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit, if the platform has the necessary exit callback events.<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTPS Response ====<br />
*Make sure that each of the Cloud API Get requests are received by the Nielsen Cloud API properly through use of the HTTPS Response Code outputs enabled in console.<br />
<br />
==== Opt-Out ====<br />
*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.<br />
*Test that the devId field is populated with a blank value if a user has elected to Opt-Out. For example: "devId": "",<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Cloud_API&diff=5158DCR Video & Static Cloud API2021-08-17T16:28:23Z<p>LaMarHolmes: /* HTTP Response Code */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
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.<br />
*For Roku Apps, please see [[DCR Video & Static Roku Cloud API]]<br />
*For Mobile Apps, please see [[DCR Video & Static Mobile Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [Unix time in ms]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2" //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || Yes<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || playhead position in seconds or Unix time in seconds || <code>"300"</code> || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp in milliseconds<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
* Playheads should be sent in seconds only, not milliseconds<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then discontinue sending playhead event updates.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
When playback is interrupted, the app needs to send delete immediately.<br />
<br />
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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
var image = new Image()<br />
image.onerror = function() {<br />
// wait and send again<br />
}<br />
(new Image).src = sessionURL+encodeURIComponent(JSON.stringify(payload));<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTPS Response Code ====<br />
<br />
Confirm request was completed by viewing HTTPS response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTPS Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
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.<br />
<br />
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.<br />
<br />
[[File:Nielsen Opt-Out.png|link=]]<br />
<br />
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). <br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement (Recommended Default Setting) || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "7be25cf9-8c40-5cc2-871e-19bf41940288",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "", //devId must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Privacy Information Template To Include In Opt-Out Screen =====<br />
<br />
<br />
Additionally, all applications must display the Nielsen privacy policy within their application, typically in the Settings/About screen of your application. The Nielsen privacy policy text is listed below.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out or opt in to Nielsen measurement, please toggle your "Limit Ad Tracking" (or similar setting) on your device, or make the appropriate selection within the application's settings. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.<br />
<br />
</blockquote><br />
'''''Disclosure Template'''''<br />
<br />
Additionally, you must update the App description information from the App Distribution Store with the Nielsen Measurement disclosure below:<br />
<br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see http://www.nielsen.com/digitalprivacy for more information.<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit, if the platform has the necessary exit callback events.<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTP Response ====<br />
*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.<br />
<br />
==== Opt-Out ====<br />
*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.<br />
*Test that the devId field is populated with a blank value if a user has elected to Opt-Out. For example: "devId": "",<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Cloud_API&diff=5157DCR Video & Static Cloud API2021-08-17T16:28:01Z<p>LaMarHolmes: /* URL Structure */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
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.<br />
*For Roku Apps, please see [[DCR Video & Static Roku Cloud API]]<br />
*For Mobile Apps, please see [[DCR Video & Static Mobile Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [Unix time in ms]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2" //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || Yes<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || playhead position in seconds or Unix time in seconds || <code>"300"</code> || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp in milliseconds<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
* Playheads should be sent in seconds only, not milliseconds<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then discontinue sending playhead event updates.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
When playback is interrupted, the app needs to send delete immediately.<br />
<br />
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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
var image = new Image()<br />
image.onerror = function() {<br />
// wait and send again<br />
}<br />
(new Image).src = sessionURL+encodeURIComponent(JSON.stringify(payload));<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTP Response Code ====<br />
<br />
Confirm request was completed by viewing HTTP response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTP Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
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.<br />
<br />
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.<br />
<br />
[[File:Nielsen Opt-Out.png|link=]]<br />
<br />
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). <br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement (Recommended Default Setting) || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "7be25cf9-8c40-5cc2-871e-19bf41940288",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Cloud API Sample App",<br />
"apv": "1",<br />
"devId": "", //devId must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Privacy Information Template To Include In Opt-Out Screen =====<br />
<br />
<br />
Additionally, all applications must display the Nielsen privacy policy within their application, typically in the Settings/About screen of your application. The Nielsen privacy policy text is listed below.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out or opt in to Nielsen measurement, please toggle your "Limit Ad Tracking" (or similar setting) on your device, or make the appropriate selection within the application's settings. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.<br />
<br />
</blockquote><br />
'''''Disclosure Template'''''<br />
<br />
Additionally, you must update the App description information from the App Distribution Store with the Nielsen Measurement disclosure below:<br />
<br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see http://www.nielsen.com/digitalprivacy for more information.<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit, if the platform has the necessary exit callback events.<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTP Response ====<br />
*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.<br />
<br />
==== Opt-Out ====<br />
*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.<br />
*Test that the devId field is populated with a blank value if a user has elected to Opt-Out. For example: "devId": "",<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Mobile_Cloud_API&diff=5156DCR Video & Static Mobile Cloud API2021-08-17T16:26:12Z<p>LaMarHolmes: /* HTTP Response */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR & DTVR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
This guide shows you how to integrate the Nielsen Cloud API to enable Digital Content Ratings (DCR) measurement on your mobile apps.<br />
*For Roku Apps, please see [[DCR Video & Static Roku Cloud API]]<br />
*For OTT Devices, please see [[DCR Video & Static Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [UTC]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2" //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
|}<br />
<br />
On mobile devices you will need to pass the IDFA/Ad ID as part of the devId parameter. Please see the section below regarding Opt Out and the IDFA/Ad ID.<br />
<br />
===== Accessing the IDFA on iOS =====<br />
<br />
Accessing the ID For Advertisers (IDFA) uses OS level API calls. In order to do this, you must first import the following header file:<br />
<syntaxhighlight lang="objective-c">#import <AdSupport/ASIdentifierManager.h></syntaxhighlight><br />
<br />
Then to receive the IDFA as a NSString, use similar code to the following:<br />
<syntaxhighlight lang="objective-c">NSString *idfaString = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];</syntaxhighlight><br />
You can read more about ASIdentifierManager on Apple's [https://developer.apple.com/reference/adsupport/asidentifiermanager| developer website].<br />
<br />
===== Accessing the Ad ID on Android =====<br />
<br />
Accessing the Google Ad ID uses OS level API calls. In order to do this, you must first import Google Play Services. Then to receive the Ad ID, use the AdvertisingIdClient class as such:<br />
<syntaxhighlight lang="java">public static AdvertisingIdClient.Info getAdvertisingIdInfo (Context context)</syntaxhighlight><br />
<br />
You can read more about the AdvertisingIdClient class on Google's [https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient| developer website].<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || Yes<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || creditable position || playhead position in seconds or Unix timestamp (seconds since Jan-1-1970 UTC) for livestream || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp in milliseconds<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then discontinue sending playhead event updates.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Pause / Play<br />
*Network Loss (Wi-Fi / Airplane Mode / Cellular)<br />
*Wi-Fi OFF / ON<br />
*Call Interrupt (SIM or Third party Skype / Hangout call)<br />
*Alarm Interrupt<br />
*Content Buffering<br />
*Device Lock / Unlock (Video players only, not for Audio players)<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
*Channel / Station Change Scenario<br />
*Unplugging of headphone<br />
<br />
When playback is temporarily interrupted (e.g. pause, content buffering), the app needs to send the last known playhead position.<br />
<br />
*If an app is sent to background for more than 5 minutes, please create a new session ID. Otherwise, use the same session ID as before.<br />
*If loss of Internet occurs, please queue the API calls that would have been made. Once Internet connectivity is regained, please spool off the API calls in order of first generated (Note: if doing so, please use the UTC time in milliseconds)<br />
<br />
When playback is permanently interrupted, the app needs to send delete immediately.<br />
*If an app crashes, please create a new session ID. No delete call will be necessary as the previous session will timeout.<br />
<br />
Once playback resumes after delete occurs, 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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
var image = new Image()<br />
image.onerror = function() {<br />
// wait and send again<br />
}<br />
(new Image).src = sessionURL+encodeURIComponent(JSON.stringify(payload));<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTPS Response Code ====<br />
<br />
Confirm request was completed by viewing HTTPS response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTPS Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
Your app must provide a means for the user to Opt-Out, or Opt-In to Nielsen Measurement. The Opt-Out requirement can be fulfilled by creating an Opt-Out/Opt-In button, toggle switch, or slider within the app "Settings", or "About" section to allow the user selection. If you have the ability to render text within the Opt-Out screen, it is recommended to add the Privacy Information included below.<br />
<br />
[[File:Nielsen Opt-Out.png|link=]]<br />
<br />
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). <br />
<br />
*In addition, you will need to ensure that the devId field is a blank value if a user has elected to Opt-Out<br />
<br />
*If the device offers "Limit Ad Tracking" or "Opt-Out" device settings, you must set uoo=true, and also ensure that the devId is set to a blank value if the user elects to enable this setting.<br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement (Recommended Default Setting) || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"devId": "7be25cf9-8c40-5cc2-871e-19bf41940288",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"devId": "", //devId must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Privacy Information Template To Include In Opt-Out Screen =====<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out, or opt into Nielsen measurement please make the appropriate selection within the app. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.<br />
</blockquote><br />
'''''Disclosure Template'''''<br />
<br />
Additionally, you must update the App description information from the App Distribution Store with the Nielsen Measurement disclosure below:<br />
<blockquote><br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see http://www.nielsen.com/digitalprivacy for more information.<br />
</blockquote><br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTPS Response ====<br />
*Make sure that each of the Cloud API Get requests are received by the Nielsen Cloud API properly through use of the HTTPS Response Code outputs enabled in console.<br />
<br />
==== Opt-Out ====<br />
*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.<br />
*Test that the devId field is populated with a blank value if a user has elected to Opt-Out. For example: "devId": "",<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Mobile_Cloud_API&diff=5155DCR Video & Static Mobile Cloud API2021-08-17T16:25:36Z<p>LaMarHolmes: /* HTTP Response Code */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR & DTVR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
This guide shows you how to integrate the Nielsen Cloud API to enable Digital Content Ratings (DCR) measurement on your mobile apps.<br />
*For Roku Apps, please see [[DCR Video & Static Roku Cloud API]]<br />
*For OTT Devices, please see [[DCR Video & Static Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [UTC]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2" //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
|}<br />
<br />
On mobile devices you will need to pass the IDFA/Ad ID as part of the devId parameter. Please see the section below regarding Opt Out and the IDFA/Ad ID.<br />
<br />
===== Accessing the IDFA on iOS =====<br />
<br />
Accessing the ID For Advertisers (IDFA) uses OS level API calls. In order to do this, you must first import the following header file:<br />
<syntaxhighlight lang="objective-c">#import <AdSupport/ASIdentifierManager.h></syntaxhighlight><br />
<br />
Then to receive the IDFA as a NSString, use similar code to the following:<br />
<syntaxhighlight lang="objective-c">NSString *idfaString = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];</syntaxhighlight><br />
You can read more about ASIdentifierManager on Apple's [https://developer.apple.com/reference/adsupport/asidentifiermanager| developer website].<br />
<br />
===== Accessing the Ad ID on Android =====<br />
<br />
Accessing the Google Ad ID uses OS level API calls. In order to do this, you must first import Google Play Services. Then to receive the Ad ID, use the AdvertisingIdClient class as such:<br />
<syntaxhighlight lang="java">public static AdvertisingIdClient.Info getAdvertisingIdInfo (Context context)</syntaxhighlight><br />
<br />
You can read more about the AdvertisingIdClient class on Google's [https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient| developer website].<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || Yes<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || creditable position || playhead position in seconds or Unix timestamp (seconds since Jan-1-1970 UTC) for livestream || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp in milliseconds<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then discontinue sending playhead event updates.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Pause / Play<br />
*Network Loss (Wi-Fi / Airplane Mode / Cellular)<br />
*Wi-Fi OFF / ON<br />
*Call Interrupt (SIM or Third party Skype / Hangout call)<br />
*Alarm Interrupt<br />
*Content Buffering<br />
*Device Lock / Unlock (Video players only, not for Audio players)<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
*Channel / Station Change Scenario<br />
*Unplugging of headphone<br />
<br />
When playback is temporarily interrupted (e.g. pause, content buffering), the app needs to send the last known playhead position.<br />
<br />
*If an app is sent to background for more than 5 minutes, please create a new session ID. Otherwise, use the same session ID as before.<br />
*If loss of Internet occurs, please queue the API calls that would have been made. Once Internet connectivity is regained, please spool off the API calls in order of first generated (Note: if doing so, please use the UTC time in milliseconds)<br />
<br />
When playback is permanently interrupted, the app needs to send delete immediately.<br />
*If an app crashes, please create a new session ID. No delete call will be necessary as the previous session will timeout.<br />
<br />
Once playback resumes after delete occurs, 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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
var image = new Image()<br />
image.onerror = function() {<br />
// wait and send again<br />
}<br />
(new Image).src = sessionURL+encodeURIComponent(JSON.stringify(payload));<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTPS Response Code ====<br />
<br />
Confirm request was completed by viewing HTTPS response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTPS Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
Your app must provide a means for the user to Opt-Out, or Opt-In to Nielsen Measurement. The Opt-Out requirement can be fulfilled by creating an Opt-Out/Opt-In button, toggle switch, or slider within the app "Settings", or "About" section to allow the user selection. If you have the ability to render text within the Opt-Out screen, it is recommended to add the Privacy Information included below.<br />
<br />
[[File:Nielsen Opt-Out.png|link=]]<br />
<br />
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). <br />
<br />
*In addition, you will need to ensure that the devId field is a blank value if a user has elected to Opt-Out<br />
<br />
*If the device offers "Limit Ad Tracking" or "Opt-Out" device settings, you must set uoo=true, and also ensure that the devId is set to a blank value if the user elects to enable this setting.<br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement (Recommended Default Setting) || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"devId": "7be25cf9-8c40-5cc2-871e-19bf41940288",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"devId": "", //devId must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Privacy Information Template To Include In Opt-Out Screen =====<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out, or opt into Nielsen measurement please make the appropriate selection within the app. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.<br />
</blockquote><br />
'''''Disclosure Template'''''<br />
<br />
Additionally, you must update the App description information from the App Distribution Store with the Nielsen Measurement disclosure below:<br />
<blockquote><br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see http://www.nielsen.com/digitalprivacy for more information.<br />
</blockquote><br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTP Response ====<br />
*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.<br />
<br />
==== Opt-Out ====<br />
*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.<br />
*Test that the devId field is populated with a blank value if a user has elected to Opt-Out. For example: "devId": "",<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Mobile_Cloud_API&diff=5154DCR Video & Static Mobile Cloud API2021-08-17T16:23:11Z<p>LaMarHolmes: /* URL Structure */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR & DTVR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
This guide shows you how to integrate the Nielsen Cloud API to enable Digital Content Ratings (DCR) measurement on your mobile apps.<br />
*For Roku Apps, please see [[DCR Video & Static Roku Cloud API]]<br />
*For OTT Devices, please see [[DCR Video & Static Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
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.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [UTC]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2" //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| devId || unique ID to identify user (e.g. Advertising ID, Roku Device ID) || custom || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
|}<br />
<br />
On mobile devices you will need to pass the IDFA/Ad ID as part of the devId parameter. Please see the section below regarding Opt Out and the IDFA/Ad ID.<br />
<br />
===== Accessing the IDFA on iOS =====<br />
<br />
Accessing the ID For Advertisers (IDFA) uses OS level API calls. In order to do this, you must first import the following header file:<br />
<syntaxhighlight lang="objective-c">#import <AdSupport/ASIdentifierManager.h></syntaxhighlight><br />
<br />
Then to receive the IDFA as a NSString, use similar code to the following:<br />
<syntaxhighlight lang="objective-c">NSString *idfaString = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];</syntaxhighlight><br />
You can read more about ASIdentifierManager on Apple's [https://developer.apple.com/reference/adsupport/asidentifiermanager| developer website].<br />
<br />
===== Accessing the Ad ID on Android =====<br />
<br />
Accessing the Google Ad ID uses OS level API calls. In order to do this, you must first import Google Play Services. Then to receive the Ad ID, use the AdvertisingIdClient class as such:<br />
<syntaxhighlight lang="java">public static AdvertisingIdClient.Info getAdvertisingIdInfo (Context context)</syntaxhighlight><br />
<br />
You can read more about the AdvertisingIdClient class on Google's [https://developers.google.com/android/reference/com/google/android/gms/ads/identifier/AdvertisingIdClient| developer website].<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"devId": "AD-ID",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || Yes<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || creditable position || playhead position in seconds or Unix timestamp (seconds since Jan-1-1970 UTC) for livestream || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp in milliseconds. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp in milliseconds<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then discontinue sending playhead event updates.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Pause / Play<br />
*Network Loss (Wi-Fi / Airplane Mode / Cellular)<br />
*Wi-Fi OFF / ON<br />
*Call Interrupt (SIM or Third party Skype / Hangout call)<br />
*Alarm Interrupt<br />
*Content Buffering<br />
*Device Lock / Unlock (Video players only, not for Audio players)<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
*Channel / Station Change Scenario<br />
*Unplugging of headphone<br />
<br />
When playback is temporarily interrupted (e.g. pause, content buffering), the app needs to send the last known playhead position.<br />
<br />
*If an app is sent to background for more than 5 minutes, please create a new session ID. Otherwise, use the same session ID as before.<br />
*If loss of Internet occurs, please queue the API calls that would have been made. Once Internet connectivity is regained, please spool off the API calls in order of first generated (Note: if doing so, please use the UTC time in milliseconds)<br />
<br />
When playback is permanently interrupted, the app needs to send delete immediately.<br />
*If an app crashes, please create a new session ID. No delete call will be necessary as the previous session will timeout.<br />
<br />
Once playback resumes after delete occurs, 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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"devId": "AD-ID", <br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
var image = new Image()<br />
image.onerror = function() {<br />
// wait and send again<br />
}<br />
(new Image).src = sessionURL+encodeURIComponent(JSON.stringify(payload));<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event", image); <br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
console.log("Event Payload", payload); <br />
</syntaxhighlight><br />
<br />
==== HTTP Response Code ====<br />
<br />
Confirm request was completed by viewing HTTP response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
code = msg.GetResponseCode();<br />
console.log("Response Code", code); <br />
</syntaxhighlight><br />
<br />
You can reference the HTTP Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
Your app must provide a means for the user to Opt-Out, or Opt-In to Nielsen Measurement. The Opt-Out requirement can be fulfilled by creating an Opt-Out/Opt-In button, toggle switch, or slider within the app "Settings", or "About" section to allow the user selection. If you have the ability to render text within the Opt-Out screen, it is recommended to add the Privacy Information included below.<br />
<br />
[[File:Nielsen Opt-Out.png|link=]]<br />
<br />
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). <br />
<br />
*In addition, you will need to ensure that the devId field is a blank value if a user has elected to Opt-Out<br />
<br />
*If the device offers "Limit Ad Tracking" or "Opt-Out" device settings, you must set uoo=true, and also ensure that the devId is set to a blank value if the user elects to enable this setting.<br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement (Recommended Default Setting) || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"devId": "7be25cf9-8c40-5cc2-871e-19bf41940288",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"devId": "", //devId must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Privacy Information Template To Include In Opt-Out Screen =====<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out, or opt into Nielsen measurement please make the appropriate selection within the app. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit http://www.nielsen.com/digitalprivacy.<br />
</blockquote><br />
'''''Disclosure Template'''''<br />
<br />
Additionally, you must update the App description information from the App Distribution Store with the Nielsen Measurement disclosure below:<br />
<blockquote><br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see http://www.nielsen.com/digitalprivacy for more information.<br />
</blockquote><br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*Upon pause, the current position should be sent, and playhead updates should stop incrementing until resume play occurs.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded<br />
<br />
==== HTTP Response ====<br />
*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.<br />
<br />
==== Opt-Out ====<br />
*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.<br />
*Test that the devId field is populated with a blank value if a user has elected to Opt-Out. For example: "devId": "",<br />
*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.<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Roku_Cloud_API&diff=5153DCR Video & Static Roku Cloud API2021-08-17T16:22:33Z<p>LaMarHolmes: /* HTTP Response */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR & DTVR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
This guide shows you how to integrate the Nielsen Cloud API to enable Digital Content Ratings (DCR) measurement on your Roku Apps.<br />
*For other OTT Apps, please see [[DCR Video & Static Cloud API]]<br />
*For Mobile Apps, please see [[DCR Video & Static Mobile Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
During testing, all calls should be pointed to the testing endpoint. Once your application has been certified, the URL should be updated to point to the Cloud API production endpoint.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [UTC]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
The session ID must be passed with every request and must remain consistent throughout each individual session.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"apn": "AppName",<br />
"encdata": "encdata=v1.key.RokuAES256CBC00.iv3x2EV0BpHH9AbZK%2FnBWWRhZbj7pD%3D...",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| encdata || Nielsen - Roku ID for Advertisers || N-RIDA Payload || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
| Example || Example || Example || Yes<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Encdata (N-RIDA): Nielsen - Roku Identifier for Advertisers =====<br />
The N-RIDA (Nielsen-Roku ID for Advertisers) is a proprietary advertising identifier that ties back to an individual Roku device, and allows Nielsen to attribute audience metrics. The N-RIDA is provided by Roku, and is pulled through the Roku <code>[https://sdkdocs.roku.com/display/sdkdoc/Integrating+the+Roku+Advertising+Framework#IntegratingtheRokuAdvertisingFramework-getNielsenContentData()asString AdIface.GetNielsenContentData()]</code> API.<br />
<br />
The N-RIDA payload should be requested once per user session and populated in the <code>"encdata"</code> Nielsen key within the <code>"devInfo"</code> payload. Each Cloud API request throughout a user session should include the same N-RIDA payload. The N-RIDA should be established when a user launches the app, and it should be maintained until the user exits. A new N-RIDA payload should be requested when the user re-enters the app.<br />
<br />
'''Prerequisites For Using The AdIface.GetNielsenContentData() Roku API'''<br />
<br />
* Roku Ad Framework (RAF) must be implemented:<br />
** <code>bs_libs_required=roku_ads_lib</code> must be included in the Roku manifest file.<br />
** <code>Library "Roku_Ads.brs"</code> should be the first entry in your Roku main.brs file.<br />
** <code>adIface = Roku_Ads()</code> allows you to access the Roku Ad Framework interface and must be called before utilizing RAF API's such as <code>AdIface.GetNielsenContentData()</code><br />
* For additional details for integrating the Roku Ad Framework (RAF) please refer to the link provided below:<br />
** https://sdkdocs.roku.com/display/sdkdoc/Integrating+the+Roku+Advertising+Framework<br />
<br />
===== Request N-RIDA for the devInfo Payload encdata parameter using AdIface.GetNielsenContentData() =====<br />
<br />
'''Example Code For Configuring Encdata'''<br />
<syntaxhighlight lang="java">// create a variable as a placeholder for the N-RIDA payload<br />
n_Rida=AdIface.GetNielsenContentData()<br />
<br />
// populate the encdata key in devInfo with the AdIface.GetNielsenContentData() retrun<br />
"devInfo": {<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"encdata": "n_Rida", //insert the AdIface.GetNielsenContentData() return within encdata<br />
"uoo": "false"<br />
}</syntaxhighlight><br />
<br />
<blockquote>'''Note''': When pulled and populated into the encdata key, the <code>AdIface.GetNielsenContentData()</code> return will be formatted similarly to the example below, and will include "encdata=" within the return along with the N-RIDA key.</blockquote><br />
<syntaxhighlight lang="json">"encdata":"encdata=v1.key.RokuAES256CBC00.iv.HSh88AM%2BG%2Fx57TZ%2BW5j5Fw%3D%3D..."</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || Yes<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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. Upon resuming content, continue to pass playhead position every 10 seconds starting at the playhead position in which content was paused. 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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || creditable position || playhead position in seconds or Unix Time for live stream || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===Example Image Request===<br />
<br />
In order to execute Cloud API calls, image requests will need to be established for each event.<br />
<br />
===Playhead Image Request Example Code===<br />
<br />
<syntaxhighlight lang="javascript"><br />
playheadRequest = CreateObject("roUrlTransfer")<br />
sendUrl = sessionUrl+playheadRequest.Escape(playheadPayload)<br />
playheadRequest.SetUrl(sendUrl)<br />
xport=CreateObject("RoMessagePort")<br />
playheadRequest.setport(xport)<br />
aa3 = {}<br />
aa3["Connection"] = "keep-alive"<br />
aa3["Content-type"] = "image/gif"<br />
playheadRequest.SetHeaders(aa3)<br />
playheadRequest.setRequest("GET")<br />
</syntaxhighlight><br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then stop passing the playhead position until content is resumed. Once content resumes, continue to pass playhead position every 10 seconds starting at the playhead position in which content was paused.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
When playback is interrupted, the app needs to send delete immediately.<br />
<br />
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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
sendUrl = sessionUrl.Escape(payload)<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
print "Playhead Event " + sendUrl<br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
print "Event Payload "+ playheadPayload + modSeq%.tostr()<br />
</syntaxhighlight><br />
<br />
==== HTTPS Response Code ====<br />
<br />
Confirm request was completed by viewing HTTPS response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
httpCode = GetResponseCode()<br />
print "Response Code " +httpCode.tostr()<br />
</syntaxhighlight><br />
<br />
You can reference the HTTPS Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
<br />
Your app must provide a means for the user to Opt-Out, or Opt-In to Nielsen Measurement. This can be implemented in two steps:<br />
<br />
==== Step 1: Nielsen Privacy Policy & Roku Channel Disclosure ====<br />
<br />
In your application, you must display the Nielsen privacy policy, which instructs users on how to opt out and opt in to Nielsen measurements. This text is usually displayed in an application's "Settings" or "About" screens.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out, or opt into Nielsen measurement please choose the appropriate "Limit Ad Tracking" setting on your device. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit https://www.nielsen.com/digitalprivacy<br />
</blockquote><br />
<br />
In addition, on your Roku Channel description, you should add the following disclosure:<br />
<br />
<blockquote><br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see https://www.nielsen.com/digitalprivacy for more information.<br />
</blockquote><br />
<br />
==== Step 2: Use "Limit Ad Tracking" setting to set User Opt Out ====<br />
<br />
Depending on the user's selection for the "Limit Ad Tracking" device setting, you should set the Cloud API <code>"uoo"</code> parameter accordingly. Roku provides an API called [https://sdkdocs.roku.com/display/sdkdoc/ifDeviceInfo#ifDeviceInfo-IsAdIdTrackingDisabled()asBoolean IsAdIdTrackingDisabled()] to check the user's limit ad tracking setting.<br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
The <code>"uoo"</code> parameter is located in the <code>"devInfo"</code> JSON object, which will be sent in every Cloud API event (playhead, complete, & delete).<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"encdata": "", //Encdata must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
Your application should check the Limit Ad Tracking setting on each app start, and/or periodically, to ensure the user's ad tracking selection is reflected in the Nielsen opt-out setting in your app.<br />
<br />
*In addition, you will need to ensure that the encdata field is populated with a blank value if a user has elected to Opt-Out.<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*When content is paused, send the current position and then stop passing playhead position until content resumes. Once content resumes, continue passing playhead position every 10 seconds starting at the position in which content was paused.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent.<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded.<br />
<br />
==== HTTPS Response ====<br />
*Make sure that each of the Cloud API Get requests are received by the Nielsen Cloud API properly through use of the HTTPS Response Code outputs enabled in console.<br />
<br />
==== Opt-Out ====<br />
*Test the "uoo" key gets populated accurately for both Opt-In and Opt-Out selections based on the device's "Limit Ad Tracking" setting.<br />
*Test that the encdata field is populated with a blank value if a user has elected to Opt-Out. For Example: "encdata": "",<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging.</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Roku_Cloud_API&diff=5152DCR Video & Static Roku Cloud API2021-08-17T16:21:51Z<p>LaMarHolmes: /* HTTPS Response Code */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR & DTVR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
This guide shows you how to integrate the Nielsen Cloud API to enable Digital Content Ratings (DCR) measurement on your Roku Apps.<br />
*For other OTT Apps, please see [[DCR Video & Static Cloud API]]<br />
*For Mobile Apps, please see [[DCR Video & Static Mobile Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
During testing, all calls should be pointed to the testing endpoint. Once your application has been certified, the URL should be updated to point to the Cloud API production endpoint.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [UTC]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
The session ID must be passed with every request and must remain consistent throughout each individual session.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"apn": "AppName",<br />
"encdata": "encdata=v1.key.RokuAES256CBC00.iv3x2EV0BpHH9AbZK%2FnBWWRhZbj7pD%3D...",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| encdata || Nielsen - Roku ID for Advertisers || N-RIDA Payload || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
| Example || Example || Example || Yes<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Encdata (N-RIDA): Nielsen - Roku Identifier for Advertisers =====<br />
The N-RIDA (Nielsen-Roku ID for Advertisers) is a proprietary advertising identifier that ties back to an individual Roku device, and allows Nielsen to attribute audience metrics. The N-RIDA is provided by Roku, and is pulled through the Roku <code>[https://sdkdocs.roku.com/display/sdkdoc/Integrating+the+Roku+Advertising+Framework#IntegratingtheRokuAdvertisingFramework-getNielsenContentData()asString AdIface.GetNielsenContentData()]</code> API.<br />
<br />
The N-RIDA payload should be requested once per user session and populated in the <code>"encdata"</code> Nielsen key within the <code>"devInfo"</code> payload. Each Cloud API request throughout a user session should include the same N-RIDA payload. The N-RIDA should be established when a user launches the app, and it should be maintained until the user exits. A new N-RIDA payload should be requested when the user re-enters the app.<br />
<br />
'''Prerequisites For Using The AdIface.GetNielsenContentData() Roku API'''<br />
<br />
* Roku Ad Framework (RAF) must be implemented:<br />
** <code>bs_libs_required=roku_ads_lib</code> must be included in the Roku manifest file.<br />
** <code>Library "Roku_Ads.brs"</code> should be the first entry in your Roku main.brs file.<br />
** <code>adIface = Roku_Ads()</code> allows you to access the Roku Ad Framework interface and must be called before utilizing RAF API's such as <code>AdIface.GetNielsenContentData()</code><br />
* For additional details for integrating the Roku Ad Framework (RAF) please refer to the link provided below:<br />
** https://sdkdocs.roku.com/display/sdkdoc/Integrating+the+Roku+Advertising+Framework<br />
<br />
===== Request N-RIDA for the devInfo Payload encdata parameter using AdIface.GetNielsenContentData() =====<br />
<br />
'''Example Code For Configuring Encdata'''<br />
<syntaxhighlight lang="java">// create a variable as a placeholder for the N-RIDA payload<br />
n_Rida=AdIface.GetNielsenContentData()<br />
<br />
// populate the encdata key in devInfo with the AdIface.GetNielsenContentData() retrun<br />
"devInfo": {<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"encdata": "n_Rida", //insert the AdIface.GetNielsenContentData() return within encdata<br />
"uoo": "false"<br />
}</syntaxhighlight><br />
<br />
<blockquote>'''Note''': When pulled and populated into the encdata key, the <code>AdIface.GetNielsenContentData()</code> return will be formatted similarly to the example below, and will include "encdata=" within the return along with the N-RIDA key.</blockquote><br />
<syntaxhighlight lang="json">"encdata":"encdata=v1.key.RokuAES256CBC00.iv.HSh88AM%2BG%2Fx57TZ%2BW5j5Fw%3D%3D..."</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || Yes<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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. Upon resuming content, continue to pass playhead position every 10 seconds starting at the playhead position in which content was paused. 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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || creditable position || playhead position in seconds or Unix Time for live stream || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===Example Image Request===<br />
<br />
In order to execute Cloud API calls, image requests will need to be established for each event.<br />
<br />
===Playhead Image Request Example Code===<br />
<br />
<syntaxhighlight lang="javascript"><br />
playheadRequest = CreateObject("roUrlTransfer")<br />
sendUrl = sessionUrl+playheadRequest.Escape(playheadPayload)<br />
playheadRequest.SetUrl(sendUrl)<br />
xport=CreateObject("RoMessagePort")<br />
playheadRequest.setport(xport)<br />
aa3 = {}<br />
aa3["Connection"] = "keep-alive"<br />
aa3["Content-type"] = "image/gif"<br />
playheadRequest.SetHeaders(aa3)<br />
playheadRequest.setRequest("GET")<br />
</syntaxhighlight><br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then stop passing the playhead position until content is resumed. Once content resumes, continue to pass playhead position every 10 seconds starting at the playhead position in which content was paused.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
When playback is interrupted, the app needs to send delete immediately.<br />
<br />
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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
sendUrl = sessionUrl.Escape(payload)<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
print "Playhead Event " + sendUrl<br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
print "Event Payload "+ playheadPayload + modSeq%.tostr()<br />
</syntaxhighlight><br />
<br />
==== HTTPS Response Code ====<br />
<br />
Confirm request was completed by viewing HTTPS response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
httpCode = GetResponseCode()<br />
print "Response Code " +httpCode.tostr()<br />
</syntaxhighlight><br />
<br />
You can reference the HTTPS Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
<br />
Your app must provide a means for the user to Opt-Out, or Opt-In to Nielsen Measurement. This can be implemented in two steps:<br />
<br />
==== Step 1: Nielsen Privacy Policy & Roku Channel Disclosure ====<br />
<br />
In your application, you must display the Nielsen privacy policy, which instructs users on how to opt out and opt in to Nielsen measurements. This text is usually displayed in an application's "Settings" or "About" screens.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out, or opt into Nielsen measurement please choose the appropriate "Limit Ad Tracking" setting on your device. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit https://www.nielsen.com/digitalprivacy<br />
</blockquote><br />
<br />
In addition, on your Roku Channel description, you should add the following disclosure:<br />
<br />
<blockquote><br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see https://www.nielsen.com/digitalprivacy for more information.<br />
</blockquote><br />
<br />
==== Step 2: Use "Limit Ad Tracking" setting to set User Opt Out ====<br />
<br />
Depending on the user's selection for the "Limit Ad Tracking" device setting, you should set the Cloud API <code>"uoo"</code> parameter accordingly. Roku provides an API called [https://sdkdocs.roku.com/display/sdkdoc/ifDeviceInfo#ifDeviceInfo-IsAdIdTrackingDisabled()asBoolean IsAdIdTrackingDisabled()] to check the user's limit ad tracking setting.<br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
The <code>"uoo"</code> parameter is located in the <code>"devInfo"</code> JSON object, which will be sent in every Cloud API event (playhead, complete, & delete).<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"encdata": "", //Encdata must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
Your application should check the Limit Ad Tracking setting on each app start, and/or periodically, to ensure the user's ad tracking selection is reflected in the Nielsen opt-out setting in your app.<br />
<br />
*In addition, you will need to ensure that the encdata field is populated with a blank value if a user has elected to Opt-Out.<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*When content is paused, send the current position and then stop passing playhead position until content resumes. Once content resumes, continue passing playhead position every 10 seconds starting at the position in which content was paused.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent.<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded.<br />
<br />
==== HTTP Response ====<br />
*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.<br />
<br />
==== Opt-Out ====<br />
*Test the "uoo" key gets populated accurately for both Opt-In and Opt-Out selections based on the device's "Limit Ad Tracking" setting.<br />
*Test that the encdata field is populated with a blank value if a user has elected to Opt-Out. For Example: "encdata": "",<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging.</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Roku_Cloud_API&diff=5151DCR Video & Static Roku Cloud API2021-08-17T16:21:10Z<p>LaMarHolmes: /* HTTP Response Code */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR & DTVR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
This guide shows you how to integrate the Nielsen Cloud API to enable Digital Content Ratings (DCR) measurement on your Roku Apps.<br />
*For other OTT Apps, please see [[DCR Video & Static Cloud API]]<br />
*For Mobile Apps, please see [[DCR Video & Static Mobile Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
During testing, all calls should be pointed to the testing endpoint. Once your application has been certified, the URL should be updated to point to the Cloud API production endpoint.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [UTC]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
The session ID must be passed with every request and must remain consistent throughout each individual session.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"apn": "AppName",<br />
"encdata": "encdata=v1.key.RokuAES256CBC00.iv3x2EV0BpHH9AbZK%2FnBWWRhZbj7pD%3D...",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| encdata || Nielsen - Roku ID for Advertisers || N-RIDA Payload || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
| Example || Example || Example || Yes<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Encdata (N-RIDA): Nielsen - Roku Identifier for Advertisers =====<br />
The N-RIDA (Nielsen-Roku ID for Advertisers) is a proprietary advertising identifier that ties back to an individual Roku device, and allows Nielsen to attribute audience metrics. The N-RIDA is provided by Roku, and is pulled through the Roku <code>[https://sdkdocs.roku.com/display/sdkdoc/Integrating+the+Roku+Advertising+Framework#IntegratingtheRokuAdvertisingFramework-getNielsenContentData()asString AdIface.GetNielsenContentData()]</code> API.<br />
<br />
The N-RIDA payload should be requested once per user session and populated in the <code>"encdata"</code> Nielsen key within the <code>"devInfo"</code> payload. Each Cloud API request throughout a user session should include the same N-RIDA payload. The N-RIDA should be established when a user launches the app, and it should be maintained until the user exits. A new N-RIDA payload should be requested when the user re-enters the app.<br />
<br />
'''Prerequisites For Using The AdIface.GetNielsenContentData() Roku API'''<br />
<br />
* Roku Ad Framework (RAF) must be implemented:<br />
** <code>bs_libs_required=roku_ads_lib</code> must be included in the Roku manifest file.<br />
** <code>Library "Roku_Ads.brs"</code> should be the first entry in your Roku main.brs file.<br />
** <code>adIface = Roku_Ads()</code> allows you to access the Roku Ad Framework interface and must be called before utilizing RAF API's such as <code>AdIface.GetNielsenContentData()</code><br />
* For additional details for integrating the Roku Ad Framework (RAF) please refer to the link provided below:<br />
** https://sdkdocs.roku.com/display/sdkdoc/Integrating+the+Roku+Advertising+Framework<br />
<br />
===== Request N-RIDA for the devInfo Payload encdata parameter using AdIface.GetNielsenContentData() =====<br />
<br />
'''Example Code For Configuring Encdata'''<br />
<syntaxhighlight lang="java">// create a variable as a placeholder for the N-RIDA payload<br />
n_Rida=AdIface.GetNielsenContentData()<br />
<br />
// populate the encdata key in devInfo with the AdIface.GetNielsenContentData() retrun<br />
"devInfo": {<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"encdata": "n_Rida", //insert the AdIface.GetNielsenContentData() return within encdata<br />
"uoo": "false"<br />
}</syntaxhighlight><br />
<br />
<blockquote>'''Note''': When pulled and populated into the encdata key, the <code>AdIface.GetNielsenContentData()</code> return will be formatted similarly to the example below, and will include "encdata=" within the return along with the N-RIDA key.</blockquote><br />
<syntaxhighlight lang="json">"encdata":"encdata=v1.key.RokuAES256CBC00.iv.HSh88AM%2BG%2Fx57TZ%2BW5j5Fw%3D%3D..."</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || Yes<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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. Upon resuming content, continue to pass playhead position every 10 seconds starting at the playhead position in which content was paused. 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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || creditable position || playhead position in seconds or Unix Time for live stream || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===Example Image Request===<br />
<br />
In order to execute Cloud API calls, image requests will need to be established for each event.<br />
<br />
===Playhead Image Request Example Code===<br />
<br />
<syntaxhighlight lang="javascript"><br />
playheadRequest = CreateObject("roUrlTransfer")<br />
sendUrl = sessionUrl+playheadRequest.Escape(playheadPayload)<br />
playheadRequest.SetUrl(sendUrl)<br />
xport=CreateObject("RoMessagePort")<br />
playheadRequest.setport(xport)<br />
aa3 = {}<br />
aa3["Connection"] = "keep-alive"<br />
aa3["Content-type"] = "image/gif"<br />
playheadRequest.SetHeaders(aa3)<br />
playheadRequest.setRequest("GET")<br />
</syntaxhighlight><br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then stop passing the playhead position until content is resumed. Once content resumes, continue to pass playhead position every 10 seconds starting at the playhead position in which content was paused.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
When playback is interrupted, the app needs to send delete immediately.<br />
<br />
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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
sendUrl = sessionUrl.Escape(payload)<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
print "Playhead Event " + sendUrl<br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
print "Event Payload "+ playheadPayload + modSeq%.tostr()<br />
</syntaxhighlight><br />
<br />
==== HTTPS Response Code ====<br />
<br />
Confirm request was completed by viewing HTTP response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
httpCode = GetResponseCode()<br />
print "Response Code " +httpCode.tostr()<br />
</syntaxhighlight><br />
<br />
You can reference the HTTPS Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
<br />
Your app must provide a means for the user to Opt-Out, or Opt-In to Nielsen Measurement. This can be implemented in two steps:<br />
<br />
==== Step 1: Nielsen Privacy Policy & Roku Channel Disclosure ====<br />
<br />
In your application, you must display the Nielsen privacy policy, which instructs users on how to opt out and opt in to Nielsen measurements. This text is usually displayed in an application's "Settings" or "About" screens.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out, or opt into Nielsen measurement please choose the appropriate "Limit Ad Tracking" setting on your device. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit https://www.nielsen.com/digitalprivacy<br />
</blockquote><br />
<br />
In addition, on your Roku Channel description, you should add the following disclosure:<br />
<br />
<blockquote><br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see https://www.nielsen.com/digitalprivacy for more information.<br />
</blockquote><br />
<br />
==== Step 2: Use "Limit Ad Tracking" setting to set User Opt Out ====<br />
<br />
Depending on the user's selection for the "Limit Ad Tracking" device setting, you should set the Cloud API <code>"uoo"</code> parameter accordingly. Roku provides an API called [https://sdkdocs.roku.com/display/sdkdoc/ifDeviceInfo#ifDeviceInfo-IsAdIdTrackingDisabled()asBoolean IsAdIdTrackingDisabled()] to check the user's limit ad tracking setting.<br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
The <code>"uoo"</code> parameter is located in the <code>"devInfo"</code> JSON object, which will be sent in every Cloud API event (playhead, complete, & delete).<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"encdata": "", //Encdata must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
Your application should check the Limit Ad Tracking setting on each app start, and/or periodically, to ensure the user's ad tracking selection is reflected in the Nielsen opt-out setting in your app.<br />
<br />
*In addition, you will need to ensure that the encdata field is populated with a blank value if a user has elected to Opt-Out.<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*When content is paused, send the current position and then stop passing playhead position until content resumes. Once content resumes, continue passing playhead position every 10 seconds starting at the position in which content was paused.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent.<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded.<br />
<br />
==== HTTP Response ====<br />
*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.<br />
<br />
==== Opt-Out ====<br />
*Test the "uoo" key gets populated accurately for both Opt-In and Opt-Out selections based on the device's "Limit Ad Tracking" setting.<br />
*Test that the encdata field is populated with a blank value if a user has elected to Opt-Out. For Example: "encdata": "",<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging.</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=DCR_Video_%26_Static_Roku_Cloud_API&diff=5150DCR Video & Static Roku Cloud API2021-08-17T16:19:35Z<p>LaMarHolmes: /* URL Structure */</p>
<hr />
<div>{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|DCR & DTVR}} {{CurrentBreadcrumb}}<br />
[[Category:Digital]]<br />
<br />
This guide shows you how to integrate the Nielsen Cloud API to enable Digital Content Ratings (DCR) measurement on your Roku Apps.<br />
*For other OTT Apps, please see [[DCR Video & Static Cloud API]]<br />
*For Mobile Apps, please see [[DCR Video & Static Mobile Cloud API]]<br />
<br />
==Prerequisites==<br />
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.<br />
<br />
<syntaxhighlight lang="javascript">XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX</syntaxhighlight><br />
<br />
==Integration==<br />
We will cover the steps for constructing the Cloud API Calls.<br />
<br />
===Request Overview===<br />
<br />
====URL Structure====<br />
<br />
The Cloud API Calls are HTTPS GET Requests with the URL structure:<br />
<br />
<syntaxhighlight lang="javascript">[endpoint]/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
The URL includes the following components:<br />
<br />
*<code>[endpoint]</code>: location of data collection environment<br />
*<code>[appid]</code>: provided App ID<br />
*<code>[sessionID]</code>: unique value for each user session<br />
*<code>[payload]</code>: metadata and events<br />
<br />
====Endpoint====<br />
<br />
There are endpoints for testing and production:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
During testing, all calls should be pointed to the testing endpoint. Once your application has been certified, the URL should be updated to point to the Cloud API production endpoint.<br />
<br />
====URL Example====<br />
As you move through the integration steps, you can reference the below URL structure with the expanded payload:<br />
<br />
<syntaxhighlight lang="javascript"><br />
https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
{<br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static_metadata],<br />
"content": [content_metadata],<br />
"ad": [ad metadata]<br />
},<br />
"event": [event],<br />
"position": [playhead_position],<br />
"type": [asset type],<br />
"utc": [UTC]<br />
}<br />
</syntaxhighlight><br />
<br />
===Create Session ID===<br />
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.<br />
<br />
The session ID must be passed with every request and must remain consistent throughout each individual session.<br />
<br />
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.<br />
<br />
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.<br />
<br />
===Define URL Structure===<br />
Define the URL structure using your provided <code>[appid]</code> and a unique <code>[sessionID]</code>.<br />
<br />
<syntaxhighlight lang="javascript">https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</syntaxhighlight><br />
<br />
===Configure Payload===<br />
<br />
All Cloud API requests must contain the following payload data:<br />
<br />
*''devInfo'': device and app info<br />
*''metadata'': asset metadata<br />
*''event metadata'': type of event<br />
<br />
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.<br />
<br />
'''Payload Example'''<br />
<br />
The example below should be referenced when following the steps for configuring the request payload.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"apn": "AppName",<br />
"encdata": "encdata=v1.key.RokuAES256CBC00.iv3x2EV0BpHH9AbZK%2FnBWWRhZbj7pD%3D...",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", //ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
</syntaxhighlight><br />
<br />
=====Configure Payload: devInfo=====<br />
An object <code>"devInfo"</code> will need to be created to capture App and Device information.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| encdata || Nielsen - Roku ID for Advertisers || N-RIDA Payload || Yes<br />
|-<br />
| apn || app name || custom || Yes<br />
|-<br />
| apv || app build version || custom || Yes<br />
|-<br />
| uoo || device opt-out status || <code>"true"</code> or <code>"false"</code> || Yes<br />
|-<br />
| Example || Example || Example || Yes<br />
|}<br />
<br />
'''Example devInfo Object'''<br />
<syntaxhighlight lang="javascript"><br />
// create devInfo object<br />
"devInfo": {<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== Encdata (N-RIDA): Nielsen - Roku Identifier for Advertisers =====<br />
The N-RIDA (Nielsen-Roku ID for Advertisers) is a proprietary advertising identifier that ties back to an individual Roku device, and allows Nielsen to attribute audience metrics. The N-RIDA is provided by Roku, and is pulled through the Roku <code>[https://sdkdocs.roku.com/display/sdkdoc/Integrating+the+Roku+Advertising+Framework#IntegratingtheRokuAdvertisingFramework-getNielsenContentData()asString AdIface.GetNielsenContentData()]</code> API.<br />
<br />
The N-RIDA payload should be requested once per user session and populated in the <code>"encdata"</code> Nielsen key within the <code>"devInfo"</code> payload. Each Cloud API request throughout a user session should include the same N-RIDA payload. The N-RIDA should be established when a user launches the app, and it should be maintained until the user exits. A new N-RIDA payload should be requested when the user re-enters the app.<br />
<br />
'''Prerequisites For Using The AdIface.GetNielsenContentData() Roku API'''<br />
<br />
* Roku Ad Framework (RAF) must be implemented:<br />
** <code>bs_libs_required=roku_ads_lib</code> must be included in the Roku manifest file.<br />
** <code>Library "Roku_Ads.brs"</code> should be the first entry in your Roku main.brs file.<br />
** <code>adIface = Roku_Ads()</code> allows you to access the Roku Ad Framework interface and must be called before utilizing RAF API's such as <code>AdIface.GetNielsenContentData()</code><br />
* For additional details for integrating the Roku Ad Framework (RAF) please refer to the link provided below:<br />
** https://sdkdocs.roku.com/display/sdkdoc/Integrating+the+Roku+Advertising+Framework<br />
<br />
===== Request N-RIDA for the devInfo Payload encdata parameter using AdIface.GetNielsenContentData() =====<br />
<br />
'''Example Code For Configuring Encdata'''<br />
<syntaxhighlight lang="java">// create a variable as a placeholder for the N-RIDA payload<br />
n_Rida=AdIface.GetNielsenContentData()<br />
<br />
// populate the encdata key in devInfo with the AdIface.GetNielsenContentData() retrun<br />
"devInfo": {<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"encdata": "n_Rida", //insert the AdIface.GetNielsenContentData() return within encdata<br />
"uoo": "false"<br />
}</syntaxhighlight><br />
<br />
<blockquote>'''Note''': When pulled and populated into the encdata key, the <code>AdIface.GetNielsenContentData()</code> return will be formatted similarly to the example below, and will include "encdata=" within the return along with the N-RIDA key.</blockquote><br />
<syntaxhighlight lang="json">"encdata":"encdata=v1.key.RokuAES256CBC00.iv.HSh88AM%2BG%2Fx57TZ%2BW5j5Fw%3D%3D..."</syntaxhighlight><br />
<br />
==== 3.2 Configure Payload: metadata ====<br />
Asset metadata can be passed through <code>"metadata"</code>. There are two asset types: <code>"content"</code> for video and <code>"ad"</code> for ads. The metadata received for each asset is used for classification and reporting.<br />
<br />
You will need to set up <code>"metadata"</code> objects for <code>"content"</code> and <code>"ad"</code> with the required Nielsen keys as shown in the sample code below.<br />
<br />
===== Content Metadata =====<br />
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of asset || <code>"content"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to asset || custom <br>(no [[Special Characters]]) || Yes<br />
|-<br />
| program ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| title ||name of program (25 character limit) || custom || Yes<br />
|-<br />
| length || length of content in seconds || <code>seconds</code> (0 for live stream) || Yes<br />
|-<br />
| segB || custom segment B || custom || No<br />
|-<br />
| segC || custom segment C || custom || No<br />
|-<br />
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes<br />
|-<br />
| isfullepisode || full episode flag || <code>"y"</code>- full episode, <code>"n"</code>- non full episode || Yes<br />
|-<br />
| crossId1 || standard episode ID || custom || Yes<br />
|-<br />
| crossId2 || content originator (only required for distributors) || Nielsen || No<br />
|-<br />
| adloadtype || type of ad load:<br />
<code>"1"</code> Linear – matches TV ad load<br />
<br />
<code>"2"</code> Dynamic – Dynamic Ad Insertion (DAI)<br />
|| <code>"2"</code> - DCR measures content with dynamic ads || Yes<br />
|-<br />
| hasAds || ads indicator<br />
<code>"1"</code>: ads included<br />
<br />
<code>"0"</code>: ads not included<br />
|| <code>"1"</code> or <code>"0"</code> || Yes<br />
|-<br />
| subbrand || sub brand override || Nielsen || No<br />
|-<br />
| progen || program genre abbreviation - see [[DCR OTT Genre List]] for accepted values || <code>"CV"</code> for Comedy Variety || Yes<br />
|}<br />
<br />
<br />
'''Example Content Object'''<br />
<syntaxhighlight lang='json'>// create content object<br />
"content": {<br />
"type": "content",<br />
"assetid": "VIDEO-ID123",<br />
"isfullepisode": "y",<br />
"program": "Program Name",<br />
"title": "Episode Title S3 - EP1",<br />
"length": "1800",<br />
"segB": "Custom Segment B",<br />
"segC": "Custom Segment C",<br />
"crossId1": "Standard Episode ID",<br />
"crossId2": "Content Originator ID",<br />
"airdate": "20161013 20:00:00",<br />
"adloadtype": "2",<br />
"hasAds": "1", <br />
"subbrand": "c05",<br />
"progen": "CV"<br />
}</syntaxhighlight><br />
<br />
===== Ad Metadata =====<br />
The ad metadata should be passed for each individual ad.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Keys !! Description !! Values !! Required<br />
|-<br />
| type || type of ad || <code>"preroll"</code>, <code>"midroll"</code>, or <code>"postroll"</code> || Yes<br />
|-<br />
| assetid || unique ID assigned to ad || custom || Yes<br />
|}<br />
<br />
===== Example Ad Object =====<br />
<syntaxhighlight lang="javascript"><br />
// create ad object<br />
"ad": {<br />
"type": "preroll",<br />
"assetid": "AD-ID123"<br />
}<br />
</syntaxhighlight><br />
<br />
=== Configure Payload: Events ===<br />
<br />
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.<br />
<br />
==== Event Types ====<br />
<br />
The available events are:<br />
{| class="wikitable"<br />
|-<br />
! Event !! Description<br />
|-<br />
| <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. Upon resuming content, continue to pass playhead position every 10 seconds starting at the playhead position in which content was paused. 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.<br />
|-<br />
| <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.<br />
|-<br />
| <code>"delete"</code> || 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).<br />
|}<br />
<br />
===== Event Parameters =====<br />
<br />
The following parameters need to be passed when calling events:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Parameter !! Description !! Value !! Required<br />
|-<br />
| <code>"event"</code> || event type || <code>"playhead"</code>, <code>"complete"</code>, or <code>"delete"</code> || Yes<br />
|-<br />
| <code>"position"</code> || creditable position || playhead position in seconds or Unix Time for live stream || Yes<br />
|-<br />
| <code>"type"</code> || asset type || <code>"content"</code>, <code>"ad"</code> || Yes<br />
|-<br />
| <code>"utc"</code> || Unix timestamp. Must be passed every 10 seconds. || <code>"1472760000000"</code> || Yes<br />
|}<br />
<br />
===== Example Event =====<br />
You can call events by passing values in the required parameters:<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": [deviceInfo],<br />
"metadata": {<br />
"static": [static metadata],<br />
"content": [content metadata],<br />
"ad": [ad metadata]<br />
},<br />
// Event Parameters<br />
"event": [event], // event name<br />
"position": [playheadPosition], //position in seconds<br />
"type": [asset type], // values are "content" or "ad"<br />
"utc": "1472760000000" //unix timestamp<br />
}<br />
</syntaxhighlight><br />
<br />
'''Note:''' The full payload including "devInfo" and "metadata" must be populated in each event request.<br />
<br />
===Example Image Request===<br />
<br />
In order to execute Cloud API calls, image requests will need to be established for each event.<br />
<br />
===Playhead Image Request Example Code===<br />
<br />
<syntaxhighlight lang="javascript"><br />
playheadRequest = CreateObject("roUrlTransfer")<br />
sendUrl = sessionUrl+playheadRequest.Escape(playheadPayload)<br />
playheadRequest.SetUrl(sendUrl)<br />
xport=CreateObject("RoMessagePort")<br />
playheadRequest.setport(xport)<br />
aa3 = {}<br />
aa3["Connection"] = "keep-alive"<br />
aa3["Content-type"] = "image/gif"<br />
playheadRequest.SetHeaders(aa3)<br />
playheadRequest.setRequest("GET")<br />
</syntaxhighlight><br />
<br />
===== Sample Event Lifecycle =====<br />
The sample event lifecycle can be used as a reference for identifying the order for calling events and values to pass.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// Start of Session: session ID created when App is opened<br />
<br />
// Preroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472760000000"} <br />
<br />
// Midroll<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Content resumes at 15 minutes<br />
Content Playhead {"event": "playhead", "position": "900", "type": "content", "utc": "1472760000000"} <br />
<br />
// Content completes at 30 minutes<br />
Complete {"event": "complete", "position": "1800", "type": "content", "utc": "1472760000000"} <br />
<br />
// Postroll<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472760000000"} <br />
</syntaxhighlight><br />
<br />
<br />
'''Sample Event Lifecycle - Detailed Storyline'''<br />
This detailed event sequence provides additional insight for the correct events to call when handling certain playback scenarios.<br />
<syntaxhighlight lang='javascript'>// SESSION STARTS<br />
// Start of Session: session ID created when App is opened<br />
<br />
// PREROLL<br />
// Preroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472760000000"} <br />
<br />
// Preroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "15", "type": "ad", "utc": "1472761500000"}<br />
<br />
// CONTENT <br />
// Content Start - Start new content streams with a position of "0" incrementing the position every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "0", "type": "content", "utc": "1472761500000"} <br />
<br />
// Content Stop Before Ad Break - Send a playhead update including the current content positon before an Ad break.<br />
Content Playhead {"event": "playhead", "position": "299", "type": "content", "utc": "1472787400000"}<br />
<br />
// MIDROLL<br />
// Midroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Midroll Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472787500000"} <br />
<br />
// Midroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "60", "type": "ad", "utc": "1472793500000"}<br />
<br />
// CONTENT<br />
// Content resumes at 5 minutes - Send playhead update with the current resumed position, and begin incrimenting the positon every 10 seconds.<br />
Content Playhead {"event": "playhead", "position": "300", "type": "content", "utc": "1472799500000"} <br />
<br />
// Content completes at 10:12 - Make sure to send in the playhead event with the final content position before sending the complete event.<br />
Final Content Playhead {"event": "playhead", "position": "612", "type": "content", "utc": "1472830700000"} <br />
<br />
Complete {"event": "complete", "position": "612", "type": "content", "utc": "1472830800000"} <br />
<br />
// POSTROLL<br />
// Postroll Start - Start each Ad with a position of "0", resetting to '0' for each Ad, and Ad break.<br />
Ad Playhead {"event": "playhead", "position": "0", "type": "ad", "utc": "1472830900000"} <br />
<br />
// Postroll Stop - End each Ad with the final position of the Ad.<br />
Ad Playhead {"event": "playhead", "position": "45", "type": "ad", "utc": "1472835300000"}<br />
<br />
// SESSION ENDS<br />
<br />
//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.<br />
Delete { "event": "delete", "position": "", "type": "", "utc": "1472835400000"} </syntaxhighlight><br />
<br />
<br />
=====Handling Playhead=====<br />
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.<br />
<br />
'''Playhead: General'''<br />
* Playhead position must start at 0 for each new asset, and be passed at least every 10 seconds.<br />
* Final postion must be sent at the end of content or an ad<br />
<br />
'''Playhead: Ads'''<br />
* The final position must be sent when switching from content to ad, or ad to content.<br />
* Each ad playhead position should be 0 at ad start.<br />
* For Ad Pods, playhead must be called, and reset to 0 for each individual ad. <br />
* The last content position before an Ad should be sent before switching to Ads.<br />
* When content has resumed following an ad break, the playhead position update must continue where the previous content segment left off.<br />
<br />
'''Playhead: User Actions'''<br />
* 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.<br />
* On pause, send the current position and then stop passing the playhead position until content is resumed. Once content resumes, continue to pass playhead position every 10 seconds starting at the playhead position in which content was paused.<br />
* If a user exits a stream early, the last current position must be sent in a playhead update to receive accurate duration.<br />
<br />
===== Interruption Scenarios =====<br />
<br />
As part of configuring events, you will need to handle all possible interruption scenarios such as:<br />
<br />
*Wi-Fi OFF / ON<br />
*App going Background / Foreground (Video players only, not for Audio players)<br />
*App Crash or Exit<br />
<br />
When playback is interrupted, the app needs to send delete immediately.<br />
<br />
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.<br />
<br />
'''Note:''' The session will automatically timeout after 30 minutes of inactivity.<br />
<br />
=== Example Request ===<br />
<br />
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.<br />
<br />
<syntaxhighlight lang="javascript"><br />
// 1. Create Session ID<br />
sessionID = dfc7dc6a-66a7-4705-9fba-adaaf7e3d5e0 // Example sessionID created using a UUID Generator<br />
<br />
// 2. Define URL Structure with App ID and Session ID<br />
sessionURL = https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=<br />
<br />
// 3. Configure Payload<br />
// 3.1 Configure Payload: devInfo <br />
payload = {<br />
"devInfo": {<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"apn": "AppName",<br />
"apv": "1.0",<br />
"uoo": "false"<br />
},<br />
<br />
// 3.2 Configure Payload: metadata<br />
"metadata": {<br />
"static": {}, // object for measuring static content<br />
"content": { // object for measuring video content<br />
"type": "content", // "content" for video<br />
"assetid": "VIDEO-ID123", // unique ID for video<br />
"isfullepisode": "y", // full episode flag<br />
"program": "Program Name", // program name<br />
"title": "Episode Title S3 - EP1", // episode name<br />
"length": "1800", // content duration in seconds<br />
"segB": "Custom Segment B", // custom segment<br />
"segC": "Custom Segment C", // custom segment<br />
"crossId1": "Standard Episode ID", // episode ID<br />
"crossId2": "Content Originator ID", // content orginator (required for distributors)<br />
"airdate": "20161013 20:00:00", // airdate<br />
"adloadtype": "2", // ad load flag<br />
"hasAds": "1", // content contains ads = 1 / no ads = 0<br />
"progen": "CV" // program genre abbreviation<br />
},<br />
"ad": {<br />
"type": "preroll", // type of ad<br />
"assetid": "AD-ID123" // unique ID for ad<br />
}<br />
},<br />
<br />
// 3.3 Configure Payload: events<br />
"event": "playhead", //event name<br />
"position": "300", // position in seconds<br />
"type": "content", //"content" or "ad"<br />
"utc": "1456448742000" //unix timestamp in milliseconds <br />
}<br />
<br />
// Append payload to URL<br />
sendUrl = sessionUrl.Escape(payload)<br />
</syntaxhighlight><br />
<br />
==== Enable Debug Logging ====<br />
<br />
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.<br />
<br />
==== GET Request ====<br />
<br />
Display GET Request to console using a name to identify each event (e.g. playhead).<br />
<br />
<syntaxhighlight lang="javascript"><br />
print "Playhead Event " + sendUrl<br />
</syntaxhighlight><br />
<br />
==== Payload ====<br />
<br />
Output payload to identify required metadata and events.<br />
<br />
<syntaxhighlight lang="javascript"><br />
print "Event Payload "+ playheadPayload + modSeq%.tostr()<br />
</syntaxhighlight><br />
<br />
==== HTTP Response Code ====<br />
<br />
Confirm request was completed by viewing HTTP response code.<br />
<br />
<syntaxhighlight lang="javascript"><br />
httpCode = GetResponseCode()<br />
print "Response Code " +httpCode.tostr()<br />
</syntaxhighlight><br />
<br />
You can reference the HTTP Response Code table when reviewing your requests:<br />
<br />
{| class="wikitable"<br />
|-<br />
! Status Code !! Status Text !! Description<br />
|-<br />
| <code>200</code> || OK || request received<br />
|-<br />
| <code>403</code> || Forbidden || invalid App ID<br />
|-<br />
| <code>404</code> || Not Found || JSON issue<br />
|}<br />
<br />
== Opt-Out ==<br />
<br />
Your app must provide a means for the user to Opt-Out, or Opt-In to Nielsen Measurement. This can be implemented in two steps:<br />
<br />
==== Step 1: Nielsen Privacy Policy & Roku Channel Disclosure ====<br />
<br />
In your application, you must display the Nielsen privacy policy, which instructs users on how to opt out and opt in to Nielsen measurements. This text is usually displayed in an application's "Settings" or "About" screens.<br />
<br />
<blockquote><br />
'''''ABOUT NIELSEN MEASUREMENT'''''<br />
<br />
Television and the way we watch it have come a long way since Nielsen began measuring TV audiences in 1950. Today, the ability to watch our favorite shows at any time and on multiple devices amplifies the need for exceptionally adept and flexible audience measurement capabilities.<br />
<br />
Consumers are changing with the times, and the same goes for us. As technology continues to evolve and media companies try new ways to attract viewers, understanding what consumers are watching — and what they're watching on — is more important than ever. Today, viewing video is a personal and mobile experience — anytime and anywhere. Our capabilities provide relevant metrics that are necessary to inform successful marketing and programming and drive continued growth. As a global information and measurement leader, we are committed to protecting the privacy and security of the data we collect, process and use. While our digital measurement products are not used to identify you in any way, they help us and our clients measure and analyze how consumers engage with media across online, mobile and emerging technologies, and offer insights into consumer behavior.<br />
<br />
'''''YOUR CHOICES'''''<br />
<br />
Nielsen believes that you should have a choice about whether to contribute to our research and insights. To opt out, or opt into Nielsen measurement please choose the appropriate "Limit Ad Tracking" setting on your device. If you have this app on more than one device, you will need to opt out of this app on each device. To learn more about our digital measurement products and your choices in regard to them, please visit https://www.nielsen.com/digitalprivacy<br />
</blockquote><br />
<br />
In addition, on your Roku Channel description, you should add the following disclosure:<br />
<br />
<blockquote><br />
This app features Nielsen's proprietary measurement software which will allow you to contribute to market research, like Nielsen's TV Ratings. Please see https://www.nielsen.com/digitalprivacy for more information.<br />
</blockquote><br />
<br />
==== Step 2: Use "Limit Ad Tracking" setting to set User Opt Out ====<br />
<br />
Depending on the user's selection for the "Limit Ad Tracking" device setting, you should set the Cloud API <code>"uoo"</code> parameter accordingly. Roku provides an API called [https://sdkdocs.roku.com/display/sdkdoc/ifDeviceInfo#ifDeviceInfo-IsAdIdTrackingDisabled()asBoolean IsAdIdTrackingDisabled()] to check the user's limit ad tracking setting.<br />
<br />
{| class="wikitable"<br />
|-<br />
! uoo Key !! Description !! Values<br />
|-<br />
| uoo || Device is Opted-In to Nielsen Measurement || <code>"false"</code><br />
|-<br />
| uoo || Device is Opted-Out of Nielsen Measurement || <code>"true"</code><br />
|}<br />
<br />
The <code>"uoo"</code> parameter is located in the <code>"devInfo"</code> JSON object, which will be sent in every Cloud API event (playhead, complete, & delete).<br />
<br />
===== devInfo Opt-In JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"encdata": "encdata=v1.key.RokuAES256CB...",<br />
"uoo": "false"<br />
},<br />
</syntaxhighlight><br />
<br />
===== devInfo Opt-Out JSON Payload Example =====<br />
<br />
<syntaxhighlight lang="javascript"><br />
"devInfo": {<br />
"apn": "Roku Sample App",<br />
"apv": "1",<br />
"encdata": "", //Encdata must be blank when a user elects to Opt-Out.<br />
"uoo": "true"<br />
},<br />
</syntaxhighlight><br />
<br />
Your application should check the Limit Ad Tracking setting on each app start, and/or periodically, to ensure the user's ad tracking selection is reflected in the Nielsen opt-out setting in your app.<br />
<br />
*In addition, you will need to ensure that the encdata field is populated with a blank value if a user has elected to Opt-Out.<br />
<br />
== Testing ==<br />
Before providing an app build to Nielsen for testing, it is important to run validation checks once you have enabled debug logging.<br />
<br />
=== Payload Validation ===<br />
<br />
Ensure that all of the required payload data is populating while testing several videos. The following areas are critical to measurement:<br />
*devInfo<br />
*Asset metadata for both content, and ads<br />
*Events<br />
*Opt-Out status<br />
<br />
=== Player Events ===<br />
Review event calls:<br />
<br />
==== playhead ====<br />
*Playhead position updates every 10 seconds starting at position '0' for each new asset.<br />
*Final playhead position is sent on content, or ad before switching between assets.<br />
*Content metadata remains constant throughout an episode, or clip play.<br />
*Ad metadata is populated appropriately for each individual ad.<br />
*Playhead position update resumes for content after an ad break, and resets to 0 for each individual ad.<br />
*For scrubbing, last current position should be sent while scrubbing occurs, and the new position should also be sent where the user scrubs to.<br />
*Exiting a stream early should execute the last current position in a playhead update to receive accurate duration.<br />
*When content is paused, send the current position and then stop passing playhead position until content resumes. Once content resumes, continue passing playhead position every 10 seconds starting at the position in which content was paused.<br />
<br />
==== complete ====<br />
*Check that the complete event executes upon content complete after the final playhead update is sent.<br />
*Do not execute the complete event for ads<br />
<br />
==== delete ====<br />
*Check to see that the delete event occurs upon app exit<br />
<br />
==== GET Request Format ====<br />
*Ensure that the event payloads are formatted in JSON<br />
*Check to see that each of the Cloud API GET requests are properly encoded.<br />
<br />
==== HTTP Response ====<br />
*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.<br />
<br />
==== Opt-Out ====<br />
*Test the "uoo" key gets populated accurately for both Opt-In and Opt-Out selections based on the device's "Limit Ad Tracking" setting.<br />
*Test that the encdata field is populated with a blank value if a user has elected to Opt-Out. For Example: "encdata": "",<br />
<br />
== Go Live ==<br />
After your integration has been certified, you will need to: Change Endpoint and Disable Logging.<br />
<br />
'''Change Endpoint:''' You will need to update to the production endpoint:<br />
<br />
*Testing: <code>https://sandbox-cloudapi.imrworldwide.com/nmapi/v2/</code><br />
*Production: <code>https://cloudapi.imrworldwide.com/nmapi/v2/</code><br />
<br />
Your production URL structure should now be:<br />
<code>https://cloudapi.imrworldwide.com/nmapi/v2/[appid]/[sessionID]/a?b=[payload]</code><br />
<br />
'''Disable Logging:''' You can now disable debug logging.</div>LaMarHolmeshttps://engineeringportal.nielsen.com//w/index.php?title=TV&diff=4748TV2021-01-22T21:38:26Z<p>LaMarHolmes: </p>
<hr />
<div>[[Category:TV]]<br />
{{Banner|Encoder Support}}<br />
<br />
<!--<br />
{{Alert|'''Download:''' '''https://nielsendownloads-blue.digitalengsdk.com/tv/REMINDER_Spring_2019_DST.pdf Reminder: Daylight Savings Time (DST) changes November 3]''' <br> '''See also:''' '''[https://nielsendownloads-blue.digitalengsdk.com/tv/Quick_Reference_Guide_Spring_2019_DST.pdf Daylight Savings Time Quick Reference Guide Spring 2019]''' }}<br />
--><br />
<br />
<!-- --><br />
{{Alert|<br />
'''DECEMBER 2019: Product Notification:'''<br><br />
'''''WATERMARK NON-LINEAR SDK Converged Encoder v5.0.23 NOW AVAILABLE''''' <br><br />
'''''Official release notification: [https://nielsendownloads.digitalengsdk.com/tv/NLM+WMSDK+Converged+Encoder+5.0.23+Release.pdf Converged Encoder 5.0.23 Release ]<br />
<br />
'''MAY 2019: Product Notification:'''<br><br />
'''''WATERMARK LINEAR SDK Converged Encoder v5.3.4 NOW AVAILABLE''''' <br><br />
'''''Official release notification: [https://nielsendownloads-blue.digitalengsdk.com/tv/Encoding/TVCBET%20v2%20Release.pdf TVCBET v2 Release ]<br />
'''''}}<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 50px;" |<br />
! Certified Vendors<br />
|-<br />
| rowspan="1" | <br />
| '''[[Nielsen Encoder Certified Vendors]]'''<br />
|-<br />
| rowspan="1" | <br />
| '''[[Nielsen Decoder Certified Vendors]]'''<br />
|-<br />
| rowspan="1" | <br />
| '''[[PCM-to-ID3 Certified Vendors]]'''<br />
|-<br />
|}<br />
<br />
{| class="wikitable"<br />
|-<br />
! style="width: 50px;" |<br />
! Reference & Policy Supplements<br />
|-<br />
| rowspan="1" | {{SmallIcon|PDFIcon.png}}<br />
| '''[https://nielsendownloads-blue.digitalengsdk.com/tv/Encoding/Encoding_Installation_and_Configuration_Policy_Rev_G.pdf Nielsen Encoder Installation and Configuration Policy]'''<br />
|-<br />
| rowspan="1" | {{SmallIcon|PDFIcon.png}}<br />
| '''[https://nielsendownloads-blue.digitalengsdk.com/tv/Encoding/Internet_Distribution_Policy_Rev_A.pdf Internet Distribution Policy]'''<br />
|-<br />
| rowspan="1" | {{SmallIcon|PDFIcon.png}}<br />
| '''[https://nielsendownloads-blue.digitalengsdk.com/tv/Encoding/Nielsen%20Encoder%20Solutions%202018.pdf Nielsen Encoder Solutions 2018]'''<br />
|-<br />
| rowspan="1" | {{SmallIcon|PDFIcon.png}}<br />
| '''[https://nielsendownloads-blue.digitalengsdk.com/tv/Encoding/MVPD%20provided%20Direct%20Feeds%20with%20Unique%20Commercial%20Content.pdf MVPD provided Direct Feeds with Unique Commercial Content]'''<br />
|-<br />
| rowspan="1" | {{SmallIcon|PDFIcon.png}}<br />
| '''[https://nielsendownloads-blue.digitalengsdk.com/tv/Encoder%20Alert%20Distribution%20List%20Instructions_Final.pdf Nielsen Encoder Alert Distribution List - Instructions]'''<br />
|}<br />
<br />
<br />
{{CategoryIcon|EncodingIcon.png|TV Audio Encoding}}<br />
{| class="wikitable"<br />
|-<br />
! style="width: 75px;" |<br />
! style="width: 35%;" | Software<br />
! style="width: 45px;" | OS <br />
! Download <br />
|-<br />
| {{SmallIcon|CircuitIcon.png}}<br />
| '''[[NWE-3GA]]''' || {{OSIcon|WindowsIcon.png}} || <br />
{{TVDownloadRequestLink|name=NWE-3GA NWE-3G Software package Rev 2.3.0.9 (New)|dlid=73aeefb5972bb1f556aa5093c14b981d223bec8e}}<br />
{{TVDownloadRequestLink|name=NWE-3GA NWE-3G Software package Rev.2.2.0.1|dlid=53fa2674bebc1a010c50b747ff969a61e4094b43}}<br />
<br />
|-<br />
<br />
| {{SmallIcon|RackIcon.png}}<br />
| '''[[NWE-TS]]'''<br />
|| {{OSIcon|FirmwareIcon.png}} || <br />
{{TVDownloadRequestLink|name=NWE-TS Firmware 4.6.10|dlid=31e04631784a2438fc41c81f34a49c33cd513ec6}} <small>''('''New!''' - June 17th, 2019)''</small><br />
{{TVDownloadRequestLink|name=NWE-TS Firmware 4.5.1|dlid=5126ebc2699eda28002ba6e2e84fb8a1031827f5}}<br />
<br />
|-<br />
<br />
| {{SmallIcon|RackIcon.png}}<br />
| '''[[Multi-Channel Encoder]]'''<br />
|| {{OSIcon|FirmwareIcon.png}} || <br />
*[[Encoder Downloads| Multi-Channel Encoder v1.2.4]]<br />
<br />
|-<br />
<br />
| {{SmallIcon|VODIcon.png}}<br />
| '''[[VOD Content Encoder]]'''<br />
|| {{OSIcon|WindowsIcon.png}} || <br />
*[[Encoder Downloads| VOD Content Encoder]]<br />
<br />
|-<br />
<br />
| {{SmallIcon|VODIcon.png}}<br />
| '''[[VOD in TV Ratings]]''' ''<small>(formerly RTVOD)</small>''<br />
|| {{OSIcon|WindowsIcon.png}} || <br />
*[[Encoder Downloads| VOD in TV Ratings]] ''<small>(formerly RTVOD)</small>''<br />
<br />
|-<br />
<br />
| {{SmallIcon|ComputerWaveIcon.png}}<br />
| '''[[SpoTTrac®]]'''<br />
|| {{OSIcon|FirmwareIcon.png}} || <br />
*[[Encoder Downloads| SpoTTrac Firmware]]<br />
<br />
|-<br />
<br />
| {{SmallIcon|EncoderGrayIcon.png}}<br />
| '''[[NAVE II]]'''<br />
|| {{OSIcon|WindowsIcon.png}} || <br />
*NAVE II Firmware v38<br />
*NAVE II Manager<br />
|-<br />
<br />
| {{SmallIcon|EncoderGrayIcon.png}}<br />
| '''[[NAVE IIC]]'''<br />
|| {{OSIcon|WindowsIcon.png}} || <br />
*NAVE IIC Firmware v3.4.15<br />
|}<br />
<br />
<br />
{{CategoryIcon|ID3Icon.png|ID3 Transcoding}}<br />
{| class="wikitable"<br />
|-<br />
! style="width: 75px;" |<br />
! style="width: 35%;" | Software<br />
! style="width: 45px;" | OS <br />
! Download <br />
<br />
|-<br />
<br />
|rowspan="3"| {{SmallIcon|ID3XcodeIcon.png}}<br />
|rowspan="3"| '''[[ID3 Transcoders]]'''<br />
|| {{OSIcon|WindowsIcon.png}} || <br />
{{TVDownloadRequestLink|name=PCM-to-ID3 SDK (Windows) v2.3.2|dlid=ac5b0e72a84b1a6e86da1a8fe0a89e24083468eb}}<br />
{{TVDownloadRequestLink|name=PCM-to-ID3 SDK (Windows Visual Studio 2013) v2.3|dlid=533cee44e69c6859e56acd9cbb38334d6b215c00}}<br />
{{TVDownloadRequestLink|name=PCM-to-ID3 SDK (Windows) v2.3 Denmark|dlid=52d99a68cd5a8e5f4787478976ef7022aaaf9433}} {{FlagIcon|DKFlagIcon.png}}<br />
{{TVDownloadRequestLink|name=PCM-to-ID3 SDK (Windows Visual Studio 2013) v2.3 Denmark|dlid=5efc850de66d9c7ca33e6f8e6cc4ac96ab13cc43}} {{FlagIcon|DKFlagIcon.png}}<br />
|-<br />
|| {{OSIcon|LinuxIcon.png}} || <br />
{{TVDownloadRequestLink|name=PCM-to-ID3 SDK (Linux x64 GLIBC 2.12) v2.3.2|dlid=c499535f6ce9a0326a408b167079e01a0596e141}}<br />
{{TVDownloadRequestLink|name=PCM-to-ID3 SDK (Linux x64 GLIBC 2.17) v2.3.2|dlid=b353e404994a1d26726b196960efe40c30427571}}<br />
{{TVDownloadRequestLink|name=PCM-to-ID3 SDK (Linux x86 GLIBC 2.17) v2.3.2|dlid=f82dfbde6f5f68ccf677b63e32fc83e68fa82cd6}}<br />
|-<br />
|| {{OSIcon|macOSIcon.png}} || <br />
{{TVDownloadRequestLink|name=PCM-to-ID3 SDK (MacOS) v2.3|dlid=3a9d04be165f39ac956278c8292cd1b87ce34b62}}<br />
<br />
|-<br />
|rowspan="1"| {{SmallIcon|ID3DashIcon.png}}<br />
|rowspan="1"| '''[[ID3 in MPEG-DASH]]'''<br />
|| {{OSIcon|StaticIcon.png}} || <br />
*[https://nielsendownloads-blue.digitalengsdk.com/tv/ID3%20Transcoding/ID3%20in%20MPEG-DASH/bbb-MPEG-DASH.zip Big Buck Bunny MPEG-DASH Nielsen Tagged]<br />
*[https://nielsendownloads-blue.digitalengsdk.com/tv/ID3%20Transcoding/ID3%20in%20MPEG-DASH/nielsenconsumer-MPEG-DASH.zip Nielsen Consumer MPEG-DASH Nielsen Tagged]<br />
*[https://nielsendownloads-blue.digitalengsdk.com/tv/ID3%20Transcoding/ID3%20in%20MPEG-DASH/nielsenxplatform-MPEG-DASH.zip Nielsen Cross Platform MPEG-DASH Nielsen Tagged]<br />
|-<br />
<br />
|rowspan="3"| {{SmallIcon|ID3ValidateIcon.png}} <br />
|rowspan="3"| '''[[PCM-to-ID3 Validator]]'''<br />
|| {{OSIcon|WindowsIcon.png}} || <br />
{{TVDownloadRequestLink|name=PCM-to-ID3 Validator (Windows) v1.8|dlid=67d34c64d1ed349c1ad92ac47adf62c877f47fcb}}<br />
|-<br />
|| {{OSIcon|LinuxIcon.png}} || <br />
{{TVDownloadRequestLink|name=PCM-to-ID3 Validator (CentOS) v1.7|dlid=dd6b62c76995aa7e1702c60e02076348ceaf573b}}<br />
|-<br />
|| {{OSIcon|macOSIcon.png}} || <br />
{{TVDownloadRequestLink|name=PCM-to-ID3 Validator (MacOS) v1.7|dlid=8053e0046589fe22645679b93ecc3c50a82637ab}}<br />
<br />
|-<br />
<br />
|rowspan="3"| {{SmallIcon|ID3ValidateIcon.png}} <br />
|rowspan="3"| '''[[PCM-to-ID3 Validator SDK]]'''<br />
|| {{OSIcon|WindowsIcon.png}} || <br />
{{TVDownloadRequestLink|name=PCM-to-ID3 Validator SDK (Windows) v1.8|dlid=78a936556ebc5caf57d2fc4d09de3a272ace9fea}}<br />
|-<br />
|| {{OSIcon|LinuxIcon.png}} || <br />
{{TVDownloadRequestLink|name=PCM-to-ID3 Validator SDK (CentOS) v1.7|dlid=ccb9af4ef45cfcf7aa4406ca63ab3b7c6efdad11}}<br />
|-<br />
|| {{OSIcon|macOSIcon.png}} || <br />
{{TVDownloadRequestLink|name=PCM-to-ID3 Validator SDK (MacOS) v1.7|dlid=05e99551d28ef4a65eab6168ad2872648346aab2}}<br />
|}<br />
<br />
<br />
{{CategoryIcon|DiagnosisToolsIcon.png|Diagnostic Tools}}<br />
{| class="wikitable"<br />
|-<br />
! style="width: 75px;" |<br />
! style="width: 35%;" | Software<br />
! style="width: 45px;" | OS <br />
! Download <br />
<br />
|-<br />
<br />
| {{SmallIcon|NACATIcon.png}} <br />
|| '''[[Nielsen Audio Code Analysis Tool|Nielsen Audio Code Analysis Tool (NACAT)]]''' <br />
|| {{OSIcon|WindowsIcon.png}} || <br />
{{TVDownloadRequestLink|name=NACAT installer (Windows) v4.3|dlid=212d5eb338cf66cd20f3846347bc3c8c6b2dfbc4}}<br />
<br />
|-<br />
<br />
| {{SmallIcon|NDICEIcon.png}}<br />
|| '''[[Nielsen Digital Code Extractor]]'''<br />
|| {{OSIcon|WindowsIcon.png}} || <br />
{{TVDownloadRequestLink|name=Nielsen Digital Code Extractor Installer|dlid=c0eb8eb1802bd08956f6e215473ef1881274a6df}} <BR> (See special installation instructions in [[Nielsen Digital Code Extractor|guide]])<br />
<br />
|-<br />
<br />
|rowspan="3"| {{SmallIcon|SDKIcon.png}} <br />
|rowspan="3"| '''[[Decoder SDK Monitor]]'''<br />
|| {{OSIcon|WindowsIcon.png}} || <br />
{{TVDownloadRequestLink|name=Decoder SDK Monitor (Windows vs2017) v1.4|dlid=b3ae411765cfa2b878c3f50c0824e61d81a58fbb}}<br />
|-<br />
|| {{OSIcon|WindowsIcon.png}} || <br />
{{TVDownloadRequestLink|name=Decoder SDK Monitor (Windows vs2015) v1.4|dlid=68d1fd697862e663a7aa2efc46377f053c983a5a}}<br />
|-<br />
|| {{OSIcon|LinuxIcon.png}} || <br />
{{TVDownloadRequestLink|name=Decoder SDK Monitor (CentOS) v1.4|dlid=c978921ba90736bf7f2c82287a0a97af89109bec}}<br />
<br />
|-<br />
<br />
| {{SmallIcon|NDICEIcon.png}}<br />
|| '''[[Nielsen Monitor Application]]'''<br />
|| {{OSIcon|WindowsIcon.png}} || <br />
{{TVDownloadRequestLink|name=Nielsen Monitor Application (Windows) v1.4|dlid=6ddf77a8f67dff67b4cbad1fee630ee80318b5bf}}<br />
<br />
|}</div>LaMarHolmes