<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://engineeringportal.nielsen.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=NielsSedat</id>
	<title>Engineering Client Portal - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://engineeringportal.nielsen.com/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=NielsSedat"/>
	<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/wiki/Special:Contributions/NielsSedat"/>
	<updated>2026-05-13T04:42:29Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.5</generator>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Norway_Audio_Browser_SDK&amp;diff=2853</id>
		<title>DCR Norway Audio Browser SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Norway_Audio_Browser_SDK&amp;diff=2853"/>
		<updated>2018-08-06T14:27:46Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: vcid-&amp;gt;subbrand&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand audio and video streaming using mobile devices, desktop browser, TV, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital Content Ratings, Digital in TV Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR). Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an AppID is needed. The AppID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration from Nielsen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  apid: &amp;quot;XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot; // eg. PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
*Add Static Queue Snippet&lt;br /&gt;
*Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Static Queue Snippet ===&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;, &amp;quot;nlsnInstance&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
===Create SDK Instance===&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
==== Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,{nol_sdkDebug: &amp;quot;debug&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following three values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter	!! Description	!! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid	|| Unique ID assigned to player/site ||	'PXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&lt;br /&gt;
|-&lt;br /&gt;
|instanceName ||	Name of SDK instance ||	&amp;quot;any string value&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug	|| Enables Nielsen console logging. Only required for testing (not in production) || &amp;quot;{nol_sdkDebug: &amp;quot;debug&amp;quot;})&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example SDK Initialization ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;PXXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX&amp;quot;, &amp;quot;nlsnInstance&amp;quot;, {nol_sdkDebug: &amp;quot;debug&amp;quot;});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;apid&amp;gt;.js, will be downloaded based on the apid and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK600.eu.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique AppID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Create Metadata Objects ===&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
*content: identify content stream&lt;br /&gt;
*ad: identify each ad&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required/Obligatory&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isAudio || indicate measurement of audio ads or audio content || &amp;lt;code&amp;gt;&amp;quot;true&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset (64 character limit)|| custom &amp;lt;br&amp;gt;(no [[Special Characters]]) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program ||(string) name of program (254 character limit) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title ||(string) episode title (max 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; ('86400' for 24/7 Livestream if only one assetid is used for the whole stream. If reporting on program level, length of the program. ) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear over-the-air broadcast || Supported formats are:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS+xx:xx&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS-xx:xx&lt;br /&gt;
&lt;br /&gt;
YYYYMMDDHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
MM-DD-YYYY&lt;br /&gt;
&lt;br /&gt;
MM/DD/YYYY&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| scheduledEndDate || the airdate when this particular asset ended in the linear over-the-air broadcast || should be same format as airdate || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches over-the-air ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || ✓&lt;br /&gt;
|-&lt;br /&gt;
| stationType	|| OTA station flag and/or OTA station type&lt;br /&gt;
||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; Custom station built per user&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; OTA streaming station with the same adload&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; OTA station with a different ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;3&amp;quot;&amp;lt;/code&amp;gt; Multicast eRadio or online station&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;4&amp;quot;&amp;lt;/code&amp;gt; On Demand Audio(podcasting)	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| stationId	|| (string) name of the channel || custom||✓&lt;br /&gt;
|-&lt;br /&gt;
| clientid	|| &lt;br /&gt;
parent ID – value is automatically populated through provided App ID.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to override the brand configured to the App ID, pass parent &amp;lt;br/&amp;gt;&lt;br /&gt;
value here and the sub-brand ID associated to that brand in the subbrand &amp;lt;br/&amp;gt;&lt;br /&gt;
key (e.g. multiple brands in App)	&lt;br /&gt;
||&lt;br /&gt;
provided by Nielsen	&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| subbrand	|| vcid/sub-brand ID – value is automatically populated through provided&amp;lt;br/&amp;gt;&lt;br /&gt;
App ID. In order to override the sub-brand configured to the App ID, value can &amp;lt;br/&amp;gt;&lt;br /&gt;
be passed here (e.g. multiple sub-brands in App). clientId does not need to be provided.&lt;br /&gt;
||&lt;br /&gt;
provided by Nielsen	&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| progen	|| (string) genre information (max 254 characters) &lt;br /&gt;
||&lt;br /&gt;
custom	&lt;br /&gt;
||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example Content Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var content_metadata_object = {  &lt;br /&gt;
  // SDK&lt;br /&gt;
  type:     'content',&lt;br /&gt;
  isAudio:  'true',&lt;br /&gt;
  assetid:  'VID123-123456',&lt;br /&gt;
  program:  'program name',&lt;br /&gt;
  title:    'episode title',&lt;br /&gt;
  length:   '543',&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example Ad Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: 'AD-1',&lt;br /&gt;
  type:    'preroll'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt; 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. &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Avoid Carriage Return (CR) and/or Linefeeds (LF) in all fields (because of current data reporting as CSV)!&lt;br /&gt;
Implementations has to filter out CR/LF with appropriate programming.&lt;br /&gt;
It's also a good idea to check and validate entries from other systems (eg. CMS, player) before simply copy them to the variables in metadata.&lt;br /&gt;
&lt;br /&gt;
== Interrupt Scenarios ==&lt;br /&gt;
&lt;br /&gt;
=== Pause Event ===&lt;br /&gt;
To indicate pause&lt;br /&gt;
&lt;br /&gt;
* Call [[stop]] immediately and withhold sending playhead position.&lt;br /&gt;
* Start sending pings – [[loadMetadata]] and [[playheadPosition]] - once the playback resumes.&lt;br /&gt;
&lt;br /&gt;
=== Other Interrupt Scenarios ===&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var stopped = false;&lt;br /&gt;
function closePlayer() {&lt;br /&gt;
	if (stopped) {return;}&lt;br /&gt;
	stopped = true;&lt;br /&gt;
	if (inMidroll) {    // Only inside a midroll indicate &amp;lt;stop&amp;gt; for the ad&lt;br /&gt;
		nSdkInstance.ggPM('stop', playheadPositionMidroll);&lt;br /&gt;
	}&lt;br /&gt;
	nSdkInstance.ggPM('end', playheadPositionContent);    // Indicate &amp;lt;end&amp;gt; for the content&lt;br /&gt;
};&lt;br /&gt;
window.addEventListener(&amp;quot;beforeunload&amp;quot;, function (e) {&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
window.addEventListener(&amp;quot;pagehide&amp;quot;, function (e) {	// for iOS mobile &amp;quot;pagehide&amp;quot; recommended by apple&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is ggPM().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
nSdkInstance.ggPM('event', parameter);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event name !! Values to pass !!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 'loadMetadata'	|| content/ad metadata object	|| Needs to be called at the beginning of each content/ad metadata object&lt;br /&gt;
|-&lt;br /&gt;
| 'setPlayheadPosition'&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;on-demoand (or ad ): || current position in seconds (integer) &amp;lt;br/&amp;gt;&lt;br /&gt;
*&amp;quot;Live: current UTC timestamp (seconds since January 1st 1970)&amp;lt;br/&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
Pass playhead position every second during playback&lt;br /&gt;
|-&lt;br /&gt;
| 'stop' ||	playhead position in seconds	|| Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| 'end'	|| playhead position in seconds	|| This event has to be called once for the current asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Playhead position as integer&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' has to be called every second&lt;br /&gt;
&lt;br /&gt;
==== Example Events ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass ( Object ):''' Content Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', contentMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass  ( Object ):''' Pre-roll AD Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', prerollMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' setPlayheadPosition  |  '''Value Pass ( Integer ):''' playheadPosition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' stop  |  '''Value Pass ( Integer ):''' stopPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('stop', stopPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' end  |  '''Value Pass ( Integer ):''' endPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('end', endPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==  SDK Event Lifecycle ==&lt;br /&gt;
&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle without ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:even browser no ads.png]]&lt;br /&gt;
&lt;br /&gt;
==== Example without ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);  // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle with ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:event browser.png|event browser.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example with ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// PREROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end pre-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);&lt;br /&gt;
&lt;br /&gt;
// MIDROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
  &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end mid-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); &lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// POSTROLL&lt;br /&gt;
nSdkInstance.ggPM('loadmetadata', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); // end post-roll stream&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
* 'setPlayheadPosition' is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling 'stop', 'end', or 'loadmetadata'.&lt;br /&gt;
&lt;br /&gt;
* after an 'end' in case there is a new content played, there is a need to have another 'loadmetadata' again.&lt;br /&gt;
&lt;br /&gt;
* For Ad, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
* When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
* For pre-roll ads you have to call the loadMetadata event for content at the start of stream and after the preroll&lt;br /&gt;
&lt;br /&gt;
== Nielsen Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/us/en/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click &amp;quot;Choices&amp;quot; to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen Online Measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/us/en/optout.html.''&lt;br /&gt;
&lt;br /&gt;
====Opt Back In====&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'debug'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
&lt;br /&gt;
====Example Production Initialization Call ====&lt;br /&gt;
Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;, &amp;quot;myPlayerName&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': before going live you have to inform Nielsen - this is necessary, because Nielsen team has to adjust internal configuration parameter to enable data collection. Without that notification no data will be collected and no data will be reported.&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Norway_Audio_App_SDK&amp;diff=2852</id>
		<title>DCR Norway Audio App SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Norway_Audio_App_SDK&amp;diff=2852"/>
		<updated>2018-08-06T14:26:27Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: /* Content metadata */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen software development kit (SDK) is one of multiple frameworks that Nielsen provides to enable measuring linear (live) and on-demand audio and video viewing using desktop computers, mobile devices, OTT devices, etc.&lt;br /&gt;
The App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK:''' The Nielsen SDK package contains a variety of sample players for your reference.&lt;br /&gt;
If you do not have any of these prerequisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] guide for information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
==  Implementation ==&lt;br /&gt;
This guide covers implementation steps for iOS using Xcode and Android using Android Studio.&lt;br /&gt;
&lt;br /&gt;
== Setting up your  Development Environment  ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
xCode|&lt;br /&gt;
&amp;lt;big&amp;gt;&lt;br /&gt;
'''Configuring Xcode Development Environment''' &lt;br /&gt;
&amp;lt;/big&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 9.0 and above.&lt;br /&gt;
&lt;br /&gt;
The SDK uses the NSURLSession instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': All communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Importing Frameworks'''&amp;lt;/big&amp;gt;&lt;br /&gt;
The first step is to ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework &lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Swift'''&amp;lt;/big&amp;gt;&lt;br /&gt;
To import a set of Objective-C files in the same app target as your Swift code, you rely on an Objective-C bridging header to expose those files to Swift. Xcode offers to create this header file when you add a Swift file to an existing Objective-C app, or an Objective-C file to an existing Swift app.&lt;br /&gt;
&lt;br /&gt;
Select File/New File/Objective-C File  &amp;lt;br /&amp;gt;&lt;br /&gt;
Xcode will prompt you to create a bridging header.&lt;br /&gt;
[[File:bridgingheader 2x.png|600px|center|link=]] &amp;lt;br /&amp;gt;&lt;br /&gt;
Once this file has been created, you need to add the following:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Objective-C'''&amp;lt;/big&amp;gt;&lt;br /&gt;
Add the code &lt;br /&gt;
&amp;lt;syntaxhighlight lang =&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 to the View Controller’s header file.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
|Android =&lt;br /&gt;
&amp;lt;big&amp;gt;'''Configuring Android Development Environment'''&amp;lt;/big&amp;gt;'&lt;br /&gt;
*The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package.&lt;br /&gt;
&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Library'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Classes/package&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== SDK Initialization ==&lt;br /&gt;
The latest version of the Nielsen App SDK allows instantiating multiple instances of the SDK object, which can be used simultaneously without any issue. The sharedInstance API that creates a singleton object was deprecated prior to version 5.1.1. (Version 4.0 for Android)&lt;br /&gt;
&lt;br /&gt;
* A maximum of four SDK instances per appid are supported. When a fifth SDK instance is launched, the SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
* When four SDK instances exist, you must destroy an old instance before creating a new one.&lt;br /&gt;
&lt;br /&gt;
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.&lt;br /&gt;
&lt;br /&gt;
* The appid is provided by the Nielsen Technical Account Manager (TAM). The appid is a GUID data type and is specific to the application.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter / Argument !! Description !! Source !! Required/Obligatory? !! Example&lt;br /&gt;
|-&lt;br /&gt;
| appid || Unique id for the application assigned by Nielsen. It is GUID data type.|| Nielsen-specified || ✓ || PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&lt;br /&gt;
|-&lt;br /&gt;
| appversion || Release version of the client app. Not needed anymore.|| custom ||  || 0.1.1&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Nielsen collection facility to which the SDK should connect.&lt;br /&gt;
'''Norway RAM integrations'''&lt;br /&gt;
* &amp;quot;nor&amp;quot;&lt;br /&gt;
|| Nielsen-specified || ✓ || &amp;quot;nor&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || Enables Nielsen console logging. Only required for testing&lt;br /&gt;
|| Nielsen-specified || required until cretification/going live || &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==== Sample SDK Initialization Code ====&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift  = &lt;br /&gt;
Swift 4.0 Example:&lt;br /&gt;
&amp;lt;code&amp;gt;NielsenInit.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
           &amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;nor&amp;quot;,&lt;br /&gt;
            &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sample code using AVPlayer.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ViewController.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class ViewController: UIViewController, NielsenAppApiDelegate, AVPictureInPictureControllerDelegate, CLLocationManagerDelegate  {&lt;br /&gt;
    &lt;br /&gt;
    let avPlayerViewController = AVPlayerViewController()&lt;br /&gt;
    var avPlayer:AVPlayer?&lt;br /&gt;
    var nielsenAppApi: NielsenAppApi!&lt;br /&gt;
&lt;br /&gt;
    override func viewDidLoad() {&lt;br /&gt;
        super.viewDidLoad()&lt;br /&gt;
&lt;br /&gt;
        self.nielsenAppApi = NielsenInit.createNielsenAppApi(delegate: self)&lt;br /&gt;
        NSLog(&amp;quot;Nielsen SDK initialized&amp;quot;)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Objective C = &lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;    &lt;br /&gt;
#import &amp;quot;NlsAppApiFactory.h&amp;quot;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@implementation NlsAppApiFactory&lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
{&lt;br /&gt;
    NSDictionary *appInformation = @{&lt;br /&gt;
                                     @&amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;sfcode&amp;quot;: &amp;quot;nor&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot;&lt;br /&gt;
                                     };&lt;br /&gt;
    return [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&lt;br /&gt;
}&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following would be the &amp;lt;code&amp;gt;NlsAppApiFactory.h&amp;lt;/code&amp;gt; file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@class NielsenAppApi;&lt;br /&gt;
@protocol NielsenAppApiDeligate;&lt;br /&gt;
&lt;br /&gt;
@interface NlsAppApiFactory : NSObject &lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppAPI *) createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;nor&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;DEBUG&amp;quot;); // only for debug builds&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&amp;lt;br /&amp;gt;&lt;br /&gt;
* Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== APP SDK Error &amp;amp; Event Codes ==&lt;br /&gt;
To view the Error and Event codes for iOS and Android, please review the [[APP SDK Event Codes|App SDK Event Code]] Reference page.&lt;br /&gt;
== Configure Payload ==&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift = &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
let channelInfo = [&lt;br /&gt;
    &amp;quot;channelName&amp;quot;: &amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
        &lt;br /&gt;
let contentMetadata = [&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
    &amp;quot;isAudio&amp;quot;: &amp;quot;true&amp;quot;,&lt;br /&gt;
    &amp;quot;assetid&amp;quot;: &amp;quot;88675545&amp;quot;,&lt;br /&gt;
    &amp;quot;title&amp;quot;: &amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
    &amp;quot;isfullepisode&amp;quot;: &amp;quot;n&amp;quot;,&lt;br /&gt;
    &amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
    &amp;quot;program&amp;quot;: &amp;quot;Program Name&amp;quot;,&lt;br /&gt;
    &amp;quot;length&amp;quot;: &amp;quot;3600&amp;quot;, &lt;br /&gt;
    &amp;quot;airdate&amp;quot;: &amp;quot;20171020 10:05:00&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;     &lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt; &lt;br /&gt;
NSDictionary  *channelInfo = @{&lt;br /&gt;
    @&amp;quot;channelName&amp;quot;:@&amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
NSDictionary *contentMetadata = @{&lt;br /&gt;
    @&amp;quot;type&amp;quot;: @&amp;quot;content&amp;quot;,&lt;br /&gt;
    @&amp;quot;isAudio&amp;quot;: @&amp;quot;true&amp;quot;,&lt;br /&gt;
    @&amp;quot;assetid&amp;quot;: [NSString stringWithFormat:@&amp;quot;ProgramAssetId-%d&amp;quot;, i],&lt;br /&gt;
    @&amp;quot;length&amp;quot;: @&amp;quot;3600&amp;quot;,&lt;br /&gt;
    @&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;,&lt;br /&gt;
    @&amp;quot;title&amp;quot;: @&amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
    @&amp;quot;isfullepisode&amp;quot;: @&amp;quot;y&amp;quot;,&lt;br /&gt;
    @&amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
    @&amp;quot;airdate&amp;quot;: &amp;quot;20161013 20:00:00&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject channelInfo = new JSONObject()&lt;br /&gt;
    .put(&amp;quot;channelname&amp;quot;, &amp;quot;My Channel Name 1&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
JSONObject contentMetadata = new JSONObject()&lt;br /&gt;
//SDK Metadata&lt;br /&gt;
    .put(&amp;quot;type&amp;quot;, &amp;quot;content&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;isAudio&amp;quot;, &amp;quot;true&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;assetid&amp;quot;, &amp;quot;vid345-67483&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;title&amp;quot;, &amp;quot;Program S3, EP1&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;length&amp;quot;, &amp;quot;3600&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;isfullepisode&amp;quot;, &amp;quot;y&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;adloadtype&amp;quot;, &amp;quot;2&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;airdate&amp;quot;, &amp;quot;20161013 20:00:00&amp;quot;)&lt;br /&gt;
  &amp;lt;/syntaxhighlight&amp;gt;   &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Configure metadata === &lt;br /&gt;
When starting a streaming session a channel info metadata object needs to be passed to the SDK containing a channelName. The name should remain constant throughout the completion of an episode or live stream.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| channelName	|| Any string representing the channel/stream	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Content metadata ===&lt;br /&gt;
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required/Obligatory&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isAudio || indicate measurement of audio ads or audio content || &amp;lt;code&amp;gt;&amp;quot;true&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset (64 character limit)|| custom &amp;lt;br&amp;gt;(no [[Special Characters]]) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program ||(string) name of program (254 character limit) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title ||(string) episode title (max 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; ('86400' for 24/7 Livestream if only one assetid is used for the whole stream. If reporting on program level, length of the program. For Event-Livestreams planned length. For on-demand stream length) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear over-the-air broadcast || Supported formats are:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS+xx:xx&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS-xx:xx&lt;br /&gt;
&lt;br /&gt;
YYYYMMDDHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
MM-DD-YYYY&lt;br /&gt;
&lt;br /&gt;
MM/DD/YYYY &lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| scheduledEndDate || the airdate when this particular asset ended in the linear over-the-air broadcast || should be same format as airdate || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches over-the-air ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || ✓&lt;br /&gt;
|-&lt;br /&gt;
| stationType	|| OTA station flag and/or OTA station type&lt;br /&gt;
||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; Custom station built per user&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; OTA streaming station with the same adload&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; OTA station with a different ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;3&amp;quot;&amp;lt;/code&amp;gt; Multicast eRadio or online station&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;4&amp;quot;&amp;lt;/code&amp;gt; On Demand Audio(podcasting)	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| stationId	|| (string) name of the channel || custom||✓&lt;br /&gt;
|-&lt;br /&gt;
| clientid	|| &lt;br /&gt;
parent ID – value is automatically populated through provided App ID.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to override the brand configured to the App ID, pass parent &amp;lt;br/&amp;gt;&lt;br /&gt;
value here and the sub-brand ID associated to that brand in the subbrand &amp;lt;br/&amp;gt;&lt;br /&gt;
key (e.g. multiple brands in App)	&lt;br /&gt;
||&lt;br /&gt;
provided by Nielsen	&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| subbrand	|| vcid/sub-brand ID – value is automatically populated through provided&amp;lt;br/&amp;gt;&lt;br /&gt;
App ID. In order to override the sub-brand configured to the App ID, value can &amp;lt;br/&amp;gt;&lt;br /&gt;
be passed here (e.g. multiple sub-brands in App). clientId does not need to be provided.&lt;br /&gt;
||&lt;br /&gt;
provided by Nielsen	&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| progen	|| (string) genre information (max 254 characters) &lt;br /&gt;
||&lt;br /&gt;
custom	&lt;br /&gt;
||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
The ad metadata (if applicable) should be passed for each individual ad, if ads are available during or before the stream begins.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Configure API Calls ==&lt;br /&gt;
=== Sample API Sequence ===&lt;br /&gt;
A Sample API sequence could follow this flow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
|On App Start||&amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadata];&amp;lt;/code&amp;gt; || // contentMetadata Object contains the JSON metadata for the impression&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;[nielsenMeter play: channelInfo];&amp;lt;/code&amp;gt; || // channelInfo contains JSON metadata of channel name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadataObject];&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;[nielsenMeter end];&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Life cycle of SDK instance ===&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## &amp;lt;code&amp;gt;appDisableApi&amp;lt;/code&amp;gt; is called&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (assign) BOOL appDisableApi;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and  [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== API Call sequence ===&lt;br /&gt;
==== Use Case 1: Content has no Advertisements ====&lt;br /&gt;
Call [[play()]] with channelName JSON as below.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
   &amp;quot;channelName&amp;quot;: &amp;quot;My Channel Name 1&amp;quot;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Call [[loadMetadata()]] with JSON metadata for content as below.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
  &amp;quot;isAudio&amp;quot;: &amp;quot;true&amp;quot;,&lt;br /&gt;
  &amp;quot;assetid&amp;quot;: &amp;quot;stream345-67483&amp;quot;,&lt;br /&gt;
  &amp;quot;program&amp;quot;: &amp;quot;ProgramName&amp;quot;,&lt;br /&gt;
  &amp;quot;title&amp;quot;: &amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
  &amp;quot;length&amp;quot;: &amp;quot;3600&amp;quot;,&lt;br /&gt;
  ...&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Call [[setPlayheadPosition()]] every one second until a pause / stop.&lt;br /&gt;
Use the sample API sequence below as a reference to identify the specific events that need to be called during content playback without ads.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;mAppSdk.play(channelInfo); &amp;lt;/code&amp;gt; || // channelInfo contains JSON metadata of channel name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.loadMetadata(contentMetaDataObject);&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // position is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;mAppSdk.end();&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Use Case 2: Content has Advertisements ====&lt;br /&gt;
Call [[play()]] with channelName JSON as below.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
   &amp;quot;channelName&amp;quot;: &amp;quot;My Channel Name 1&amp;quot;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Call [[loadMetadata()]] with JSON metadata for ad as below.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
   &amp;quot;type&amp;quot;: &amp;quot;preroll&amp;quot;,&lt;br /&gt;
   &amp;quot;assetid&amp;quot;: &amp;quot;ad=123&amp;quot;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Note: In case the individual ad details are not available, send ad pod (presence) details through the [[loadMetadata]] and playhead position through [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Call [[setPlayheadPosition()]] every one second until a pause / stop / another [[loadMetadata()]] is called. Playhead should be passed for the entire duration of ad pod, if the ad pod details are passed as part of [[loadMetadata()]].&lt;br /&gt;
&lt;br /&gt;
The sample API sequence can be used as a reference to identify the specific events that need to be called during content and ad playback.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;mAppSdk.play(channelInfo); &amp;lt;/code&amp;gt; || // channelName contains JSON metadata of channel name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.loadMetadata(contentMetaDataObject);&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | Preroll || &amp;lt;code&amp;gt;mAppSdk.loadMetadata(prerollMetadataObject);&amp;lt;/code&amp;gt; || // prerollMetadataObject contains the JSON metadata for the preroll ad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // position is position of the playhead while the preroll ad is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.stop();&amp;lt;/code&amp;gt; || // Call stop after preroll occurs&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | Content || &amp;lt;code&amp;gt;mAppSdk.loadMetadata(contentMetaDataObject);&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // position is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.stop();&amp;lt;/code&amp;gt; || // Call stop after the content is paused (ad starts)&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;6&amp;quot; | Midroll || &amp;lt;code&amp;gt;mAppSdk.loadMetadata(midrollMetaDataObject);&amp;lt;/code&amp;gt; || // midrollMetadataObject contains the JSON metadata for the midroll ad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // position is position of the playhead while the midroll ad is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.stop();&amp;lt;/code&amp;gt; || // App moves to background(midroll pauses) &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.loadMetadata(midrollMetaDataObject);&amp;lt;/code&amp;gt; || // App moves to foreground (midroll resumes) &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the midroll ad is being played &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.stop();&amp;lt;/code&amp;gt; || // Call stop after midroll occurs&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | Content (End of stream) || &amp;lt;code&amp;gt;mAppSdk.loadMetadata(contentMetaDataObject);&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // position is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.stop();&amp;lt;/code&amp;gt; || // Always call stop irrespective of postroll is followed or not&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;mAppSdk.end();&amp;lt;/code&amp;gt; || // Call end() at the end of content&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | Postroll || &amp;lt;code&amp;gt;mAppSdk.loadMetadata(postrollMetaDataObject);&amp;lt;/code&amp;gt; || // postrollMetadataObject contains the JSON metadata for the postroll ad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // position is position of the playhead while the postroll ad is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.stop();&amp;lt;/code&amp;gt; || // Call stop after postroll occurs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Note: Each Ad playhead should reset or begin from 0 at ad start. When content has resumed following an ad break, playhead position must continue from where previous content segment was left off.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence of Calls ===&lt;br /&gt;
&lt;br /&gt;
=== play ===&lt;br /&gt;
Use [[play]] to pass the channel information containing the channelName parameter when the streaming session starts.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt; - (void)play:(id)channelInfo;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;nielsenAppApi?.play(channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
The loadMetadata function is used to inform the SDK about new content. The contentMetadata object passed in should contain the values as described above.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void)loadMetadata:(id)contentMetadata;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void loadMetadata(JSONObject contentMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.loadMetadata(contentMetadata)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== playheadPosition ===&lt;br /&gt;
Use playheadPosition to tell the SDK about the current position in the stream. For live content this should be the UTC timestamp in seconds, for on-demand content simply the second in the stream.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void) playheadPosition: (long long) playheadPos;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Sending playheadposition for content ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
AVPlayer *player;&lt;br /&gt;
CMTime curTime=[player currentTime];&lt;br /&gt;
int pos = CMTimeGetSeconds(curTime);&lt;br /&gt;
[nAppApiObject playheadPosition:pos];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
        //Monitor the Playhead position of the AVPlayer&lt;br /&gt;
        let timeInterval: CMTime = CMTimeMakeWithSeconds(1.0,10)&lt;br /&gt;
        self.avPlayerViewController.player?.addPeriodicTimeObserver(forInterval: timeInterval, queue: DispatchQueue.main) {(elapsedTime: CMTime) -&amp;gt; Void in&lt;br /&gt;
            if self.avPlayerViewController.player!.currentItem?.status == .readyToPlay {&lt;br /&gt;
                let time : Float64 = self.avPlayerViewController.player!.currentTime().seconds;&lt;br /&gt;
                let pos = Int64(time);&lt;br /&gt;
                NSLog(&amp;quot;New Elapse Time = \(time)&amp;quot;);&lt;br /&gt;
                self.nielsenAppApi?.playheadPosition(pos);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void setPlayheadPosition(long position);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== stop ===&lt;br /&gt;
Tell the SDK that content playback has stopped.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void) stop;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== end ===&lt;br /&gt;
When content stop is initiated and content cannot be resumed from the same position. For example when the stream has reached its end or in situations where it can only be restarted from the beginning.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;- (void) end;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void end();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.end();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Interruptions during playback ==&lt;br /&gt;
As part of integrating Nielsen App SDK with the player application, the Audio / Video app developer needs to handle the following possible interruption scenarios:&lt;br /&gt;
* Pause / Play&lt;br /&gt;
* Network Loss (Wi-Fi / Airplane / Cellular)&lt;br /&gt;
* Call Interrupt (SIM or Third party Skype / Hangout call)&lt;br /&gt;
* Alarm Interrupt&lt;br /&gt;
* Content Buffering&lt;br /&gt;
* Device Lock / Unlock (For Audio players only if audio stops playing)&lt;br /&gt;
* App going in the Background/Foreground (For Audio players only if audio stops playing)&lt;br /&gt;
* Channel / Station Change Scenario&lt;br /&gt;
* Unplugging of headphone&lt;br /&gt;
In case of encountering one of the above interruptions, the player application needs to&lt;br /&gt;
* Call [[stop]] immediately (except when content is buffering) and withhold sending playhead position.&lt;br /&gt;
* Start sending pings – [[loadMetadata]] and [[playheadPosition]] for the new viewing session, once the playback resumes.&lt;br /&gt;
Please see the [[Digital Measurement FAQ]] for more details&lt;br /&gt;
&lt;br /&gt;
== Privacy and Opt-Out ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
&lt;br /&gt;
iOS| &lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to the page referenced by the opt-out url provided by the SDK. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL for the Nielsen Privacy web page should be retrieved from the optOutURL property of the SDK object &amp;lt;code&amp;gt;optOutURL&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL in the optOutURL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- === Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = nAppApiObject.optOutURL;&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:App optout en1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Android = &lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to page referenced by the opt-out url provided by the SDK. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking &amp;lt;code&amp;gt;userOptOutURLString()&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public String userOptOutURLString()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the &amp;lt;code&amp;gt; getOptOutStatus() &amp;lt;/code&amp;gt; method.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean getOptOutStatus()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy App.png|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
*SDK will be sending the data pings to census even though the user opted out. However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make one update to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_devDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;iOS Example:&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
            &amp;quot;appid&amp;quot;: &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;nor&amp;quot;&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Android Example:&amp;lt;/big&amp;gt;''' &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;nor&amp;quot;)&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': before going live you have to inform Nielsen team - this is necessary, because Nielsen team has to adjust internal configuration parameter to enable data collection. Without that notification no data will be collected and no data will be reported.&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Norway_Audio_Browser_SDK&amp;diff=2803</id>
		<title>DCR Norway Audio Browser SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Norway_Audio_Browser_SDK&amp;diff=2803"/>
		<updated>2018-06-11T14:46:07Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand audio and video streaming using mobile devices, desktop browsert, TV, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital Content Ratings, Digital in TV Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR). Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an AppID is needed. The AppID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration from Nielsen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  apid: &amp;quot;XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot; // eg. PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
*Add Static Queue Snippet&lt;br /&gt;
*Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Static Queue Snippet ===&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;, &amp;quot;nlsnInstance&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
===Create SDK Instance===&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
==== Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,{nol_sdkDebug: &amp;quot;debug&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following three values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter	!! Description	!! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid	|| Unique ID assigned to player/site ||	'PXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&lt;br /&gt;
|-&lt;br /&gt;
|instanceName ||	Name of SDK instance ||	&amp;quot;any string value&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug	|| Enables Nielsen console logging. Only required for testing (not in production) || &amp;quot;{nol_sdkDebug: &amp;quot;debug&amp;quot;})&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example SDK Initialization ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;PXXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX&amp;quot;, &amp;quot;nlsnInstance&amp;quot;, {nol_sdkDebug: &amp;quot;debug&amp;quot;});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;apid&amp;gt;.js, will be downloaded based on the apid and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK600.eu.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique AppID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Create Metadata Objects ===&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
*content: identify content stream&lt;br /&gt;
*ad: identify each ad&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required/Obligatory&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isAudio || indicate measurement of audio ads or audio content || &amp;lt;code&amp;gt;&amp;quot;true&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset (64 character limit)|| custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program ||(string) name of program (254 character limit) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title ||(string) episode title (max 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; ('86400' for 24/7 Livestream if only one assetid is used for the whole stream. If reporting on program level, length of the program. ) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear over-the-air broadcast || Supported formats are:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS+xx:xx&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS-xx:xx&lt;br /&gt;
&lt;br /&gt;
YYYYMMDDHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
MM-DD-YYYY&lt;br /&gt;
&lt;br /&gt;
MM/DD/YYYY&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| scheduledEndDate || the airdate when this particular asset ended in the linear over-the-air broadcast || should be same format as airdate || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches over-the-air ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || ✓&lt;br /&gt;
|-&lt;br /&gt;
| stationType	|| OTA station flag and/or OTA station type&lt;br /&gt;
||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; Custom station built per user&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; OTA streaming station with the same adload&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; OTA station with a different ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;3&amp;quot;&amp;lt;/code&amp;gt; Multicast eRadio or online station&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;4&amp;quot;&amp;lt;/code&amp;gt; On Demand Audio(podcasting)	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| stationId	|| (string) name of the channel || custom||✓&lt;br /&gt;
|-&lt;br /&gt;
| clientid	|| &lt;br /&gt;
parent ID – value is automatically populated through provided App ID.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to override the brand configured to the App ID, pass parent &amp;lt;br/&amp;gt;&lt;br /&gt;
value here and the sub-brand ID associated to that brand in the subbrand &amp;lt;br/&amp;gt;&lt;br /&gt;
key (e.g. multiple brands in App)	&lt;br /&gt;
||&lt;br /&gt;
provided by Nielsen	&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| vcid	|| vcid/sub-brand ID – value is automatically populated through provided&amp;lt;br/&amp;gt;&lt;br /&gt;
App ID. In order to override the sub-brand configured to the App ID, value can &amp;lt;br/&amp;gt;&lt;br /&gt;
be passed here (e.g. multiple sub-brands in App). clientId does not need to be provided.&lt;br /&gt;
||&lt;br /&gt;
provided by Nielsen	&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| progen	|| (string) genre information (max 254 characters) &lt;br /&gt;
||&lt;br /&gt;
custom	&lt;br /&gt;
||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example Content Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var content_metadata_object = {  &lt;br /&gt;
  // SDK&lt;br /&gt;
  type:     'content',&lt;br /&gt;
  isAudio:  'true',&lt;br /&gt;
  assetid:  'VID123-123456',&lt;br /&gt;
  program:  'program name',&lt;br /&gt;
  title:    'episode title',&lt;br /&gt;
  length:   '543',&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example Ad Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: 'AD-1',&lt;br /&gt;
  type:    'preroll'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt; 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. &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Avoid Carriage Return (CR) and/or Linefeeds (LF) in all fields (because of current data reporting as CSV)!&lt;br /&gt;
Implementations has to filter out CR/LF with appropriate programming.&lt;br /&gt;
It's also a good idea to check and validate entries from other systems (eg. CMS, player) before simply copy them to the variables in metadata.&lt;br /&gt;
&lt;br /&gt;
== Interrupt Scenarios ==&lt;br /&gt;
&lt;br /&gt;
=== Pause Event ===&lt;br /&gt;
To indicate pause&lt;br /&gt;
&lt;br /&gt;
* Call [[stop]] immediately and withhold sending playhead position.&lt;br /&gt;
* Start sending pings – [[loadMetadata]] and [[playheadPosition]] - once the playback resumes.&lt;br /&gt;
&lt;br /&gt;
=== Other Interrupt Scenarios ===&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var stopped = false;&lt;br /&gt;
function closePlayer() {&lt;br /&gt;
	if (stopped) {return;}&lt;br /&gt;
	stopped = true;&lt;br /&gt;
	if (inMidroll) {    // Only inside a midroll indicate &amp;lt;stop&amp;gt; for the ad&lt;br /&gt;
		nSdkInstance.ggPM('stop', playheadPositionMidroll);&lt;br /&gt;
	}&lt;br /&gt;
	nSdkInstance.ggPM('end', playheadPositionContent);    // Indicate &amp;lt;end&amp;gt; for the content&lt;br /&gt;
};&lt;br /&gt;
window.addEventListener(&amp;quot;beforeunload&amp;quot;, function (e) {&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
window.addEventListener(&amp;quot;pagehide&amp;quot;, function (e) {	// for iOS mobile &amp;quot;pagehide&amp;quot; recommended by apple&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is ggPM().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
nSdkInstance.ggPM('event', parameter);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event name !! Values to pass !!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 'loadMetadata'	|| content/ad metadata object	|| Needs to be called at the beginning of each content/ad metadata object&lt;br /&gt;
|-&lt;br /&gt;
| 'setPlayheadPosition'&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;on-demoand (or ad ): || current position in seconds (integer) &amp;lt;br/&amp;gt;&lt;br /&gt;
*&amp;quot;Live: current UTC timestamp (seconds since January 1st 1970)&amp;lt;br/&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
Pass playhead position every second during playback&lt;br /&gt;
|-&lt;br /&gt;
| 'stop' ||	playhead position in seconds	|| Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| 'end'	|| playhead position in seconds	|| This event has to be called once for the current asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Playhead position as integer&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' has to be called every second&lt;br /&gt;
&lt;br /&gt;
==== Example Events ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass ( Object ):''' Content Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', contentMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass  ( Object ):''' Pre-roll AD Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', prerollMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' setPlayheadPosition  |  '''Value Pass ( Integer ):''' playheadPosition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' stop  |  '''Value Pass ( Integer ):''' stopPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('stop', stopPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' end  |  '''Value Pass ( Integer ):''' endPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('end', endPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==  SDK Event Lifecycle ==&lt;br /&gt;
&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle without ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:even browser no ads.png]]&lt;br /&gt;
&lt;br /&gt;
==== Example without ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);  // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle with ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:event browser.png|event browser.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example with ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// PREROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end pre-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);&lt;br /&gt;
&lt;br /&gt;
// MIDROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
  &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end mid-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); &lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// POSTROLL&lt;br /&gt;
nSdkInstance.ggPM('loadmetadata', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); // end post-roll stream&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
* 'setPlayheadPosition' is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling 'stop', 'end', or 'loadmetadata'.&lt;br /&gt;
&lt;br /&gt;
* after an 'end' in case there is a new content played, there is a need to have another 'loadmetadata' again.&lt;br /&gt;
&lt;br /&gt;
* For Ad, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
* When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
* For pre-roll ads you have to call the loadMetadata event for content at the start of stream and after the preroll&lt;br /&gt;
&lt;br /&gt;
== Nielsen Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/de/de/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click &amp;quot;Choices&amp;quot; to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen Online Measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/de/de/optout.html.''&lt;br /&gt;
&lt;br /&gt;
====Opt Back In====&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'debug'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
&lt;br /&gt;
====Example Production Initialization Call ====&lt;br /&gt;
Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;, &amp;quot;myPlayerName&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': before going live you have to inform Nielsen - this is necessary, because Nielsen team has to adjust internal configuration parameter to enable data collection. Without that notification no data will be collected and no data will be reported.&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Norway_Audio_Browser_SDK&amp;diff=2802</id>
		<title>DCR Norway Audio Browser SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Norway_Audio_Browser_SDK&amp;diff=2802"/>
		<updated>2018-06-11T14:45:53Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand audio and video streaming using mobile devices, desktop browsert, TV, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital Content Ratings, Digital in TV Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR). Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an AppID is needed. The AppID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration from Nielsen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  apid: &amp;quot;XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot; // eg. PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
*Add Static Queue Snippet&lt;br /&gt;
*Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Static Queue Snippet ===&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;, &amp;quot;nlsnInstance&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
===Create SDK Instance===&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
==== Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,{nol_sdkDebug: &amp;quot;debug&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following three values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter	!! Description	!! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid	|| Unique ID assigned to player/site ||	'PXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&lt;br /&gt;
|-&lt;br /&gt;
|instanceName ||	Name of SDK instance ||	&amp;quot;any string value&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug	|| Enables Nielsen console logging. Only required for testing (not in production) || &amp;quot;{nol_sdkDebug: &amp;quot;debug&amp;quot;})&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example SDK Initialization ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;PXXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX&amp;quot;, &amp;quot;nlsnInstance&amp;quot;, {nol_sdkDebug: &amp;quot;debug&amp;quot;});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;apid&amp;gt;.js, will be downloaded based on the apid and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK600.eu.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique AppID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Create Metadata Objects ===&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
*content: identify content stream&lt;br /&gt;
*ad: identify each ad&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required/Obligatory&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isAudio || indicate measurement of audio ads or audio content || &amp;lt;code&amp;gt;&amp;quot;true&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset (64 character limit)|| custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program ||(string) name of program (254 character limit) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title ||(string) episode title (max 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; ('86400' for 24/7 Livestream if only one assetid is used for the whole stream. If reporting on program level, length of the program. ) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear over-the-air broadcast || Supported formats are:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS+xx:xx&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS-xx:xx&lt;br /&gt;
&lt;br /&gt;
YYYYMMDDHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
MM-DD-YYYY&lt;br /&gt;
&lt;br /&gt;
MM/DD/YYYY&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| scheduledEndDate || the airdate when this particular asset ended in the linear over-the-air broadcast || should be same format as airdate || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches over-the-air ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || ✓&lt;br /&gt;
|-&lt;br /&gt;
| stationType	|| OTA station flag and/or OTA station type&lt;br /&gt;
||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; Custom station built per user&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; OTA streaming station with the same adload&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; OTA station with a different ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;3&amp;quot;&amp;lt;/code&amp;gt; Multicast eRadio or online station&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;4&amp;quot;&amp;lt;/code&amp;gt; On Demand Audio(podcasting)	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| stationId	|| (string) name of the channel || custom||✓&lt;br /&gt;
|-&lt;br /&gt;
| clientid	|| &lt;br /&gt;
parent ID – value is automatically populated through provided App ID.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to override the brand configured to the App ID, pass parent &amp;lt;br/&amp;gt;&lt;br /&gt;
value here and the sub-brand ID associated to that brand in the subbrand &amp;lt;br/&amp;gt;&lt;br /&gt;
key (e.g. multiple brands in App)	&lt;br /&gt;
||&lt;br /&gt;
provided by Nielsen	&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| vcid	|| vcid/sub-brand ID – value is automatically populated through provided&amp;lt;br/&amp;gt;&lt;br /&gt;
App ID. In order to override the sub-brand configured to the App ID, value can &amp;lt;br/&amp;gt;&lt;br /&gt;
be passed here (e.g. multiple sub-brands in App). clientId does not need to be provided.&lt;br /&gt;
||&lt;br /&gt;
provided by Nielsen	&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| progen	|| (string) genre information (max 254 characters) &lt;br /&gt;
||&lt;br /&gt;
custom	&lt;br /&gt;
||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example Content Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var content_metadata_object = {  &lt;br /&gt;
  // SDK&lt;br /&gt;
  type:     'content',&lt;br /&gt;
  isAudio:   'true',&lt;br /&gt;
  assetid:  'VID123-123456',&lt;br /&gt;
  program:  'program name',&lt;br /&gt;
  title:    'episode title',&lt;br /&gt;
  length:   '543',&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example Ad Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: 'AD-1',&lt;br /&gt;
  type:    'preroll'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt; 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. &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Avoid Carriage Return (CR) and/or Linefeeds (LF) in all fields (because of current data reporting as CSV)!&lt;br /&gt;
Implementations has to filter out CR/LF with appropriate programming.&lt;br /&gt;
It's also a good idea to check and validate entries from other systems (eg. CMS, player) before simply copy them to the variables in metadata.&lt;br /&gt;
&lt;br /&gt;
== Interrupt Scenarios ==&lt;br /&gt;
&lt;br /&gt;
=== Pause Event ===&lt;br /&gt;
To indicate pause&lt;br /&gt;
&lt;br /&gt;
* Call [[stop]] immediately and withhold sending playhead position.&lt;br /&gt;
* Start sending pings – [[loadMetadata]] and [[playheadPosition]] - once the playback resumes.&lt;br /&gt;
&lt;br /&gt;
=== Other Interrupt Scenarios ===&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var stopped = false;&lt;br /&gt;
function closePlayer() {&lt;br /&gt;
	if (stopped) {return;}&lt;br /&gt;
	stopped = true;&lt;br /&gt;
	if (inMidroll) {    // Only inside a midroll indicate &amp;lt;stop&amp;gt; for the ad&lt;br /&gt;
		nSdkInstance.ggPM('stop', playheadPositionMidroll);&lt;br /&gt;
	}&lt;br /&gt;
	nSdkInstance.ggPM('end', playheadPositionContent);    // Indicate &amp;lt;end&amp;gt; for the content&lt;br /&gt;
};&lt;br /&gt;
window.addEventListener(&amp;quot;beforeunload&amp;quot;, function (e) {&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
window.addEventListener(&amp;quot;pagehide&amp;quot;, function (e) {	// for iOS mobile &amp;quot;pagehide&amp;quot; recommended by apple&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is ggPM().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
nSdkInstance.ggPM('event', parameter);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event name !! Values to pass !!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 'loadMetadata'	|| content/ad metadata object	|| Needs to be called at the beginning of each content/ad metadata object&lt;br /&gt;
|-&lt;br /&gt;
| 'setPlayheadPosition'&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;on-demoand (or ad ): || current position in seconds (integer) &amp;lt;br/&amp;gt;&lt;br /&gt;
*&amp;quot;Live: current UTC timestamp (seconds since January 1st 1970)&amp;lt;br/&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
Pass playhead position every second during playback&lt;br /&gt;
|-&lt;br /&gt;
| 'stop' ||	playhead position in seconds	|| Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| 'end'	|| playhead position in seconds	|| This event has to be called once for the current asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Playhead position as integer&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' has to be called every second&lt;br /&gt;
&lt;br /&gt;
==== Example Events ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass ( Object ):''' Content Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', contentMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass  ( Object ):''' Pre-roll AD Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', prerollMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' setPlayheadPosition  |  '''Value Pass ( Integer ):''' playheadPosition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' stop  |  '''Value Pass ( Integer ):''' stopPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('stop', stopPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' end  |  '''Value Pass ( Integer ):''' endPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('end', endPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==  SDK Event Lifecycle ==&lt;br /&gt;
&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle without ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:even browser no ads.png]]&lt;br /&gt;
&lt;br /&gt;
==== Example without ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);  // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle with ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:event browser.png|event browser.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example with ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// PREROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end pre-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);&lt;br /&gt;
&lt;br /&gt;
// MIDROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
  &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end mid-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); &lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// POSTROLL&lt;br /&gt;
nSdkInstance.ggPM('loadmetadata', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); // end post-roll stream&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
* 'setPlayheadPosition' is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling 'stop', 'end', or 'loadmetadata'.&lt;br /&gt;
&lt;br /&gt;
* after an 'end' in case there is a new content played, there is a need to have another 'loadmetadata' again.&lt;br /&gt;
&lt;br /&gt;
* For Ad, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
* When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
* For pre-roll ads you have to call the loadMetadata event for content at the start of stream and after the preroll&lt;br /&gt;
&lt;br /&gt;
== Nielsen Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/de/de/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click &amp;quot;Choices&amp;quot; to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen Online Measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/de/de/optout.html.''&lt;br /&gt;
&lt;br /&gt;
====Opt Back In====&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'debug'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
&lt;br /&gt;
====Example Production Initialization Call ====&lt;br /&gt;
Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;, &amp;quot;myPlayerName&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': before going live you have to inform Nielsen - this is necessary, because Nielsen team has to adjust internal configuration parameter to enable data collection. Without that notification no data will be collected and no data will be reported.&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Norway_Audio_Browser_SDK&amp;diff=2801</id>
		<title>DCR Norway Audio Browser SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Norway_Audio_Browser_SDK&amp;diff=2801"/>
		<updated>2018-06-11T14:44:56Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand audio and video streaming using mobile devices, desktop browsert, TV, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital Content Ratings, Digital in TV Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR). Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an AppID is needed. The AppID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration from Nielsen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  apid: &amp;quot;XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot; // eg. PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
*Add Static Queue Snippet&lt;br /&gt;
*Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Static Queue Snippet ===&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;, &amp;quot;nlsnInstance&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
===Create SDK Instance===&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
==== Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,{nol_sdkDebug: &amp;quot;debug&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following three values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter	!! Description	!! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid	|| Unique ID assigned to player/site ||	'PXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&lt;br /&gt;
|-&lt;br /&gt;
|instanceName ||	Name of SDK instance ||	&amp;quot;any string value&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug	|| Enables Nielsen console logging. Only required for testing (not in production) || &amp;quot;{nol_sdkDebug: &amp;quot;debug&amp;quot;})&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example SDK Initialization ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;PXXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX&amp;quot;, &amp;quot;nlsnInstance&amp;quot;, {nol_sdkDebug: &amp;quot;debug&amp;quot;});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;apid&amp;gt;.js, will be downloaded based on the apid and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK600.eu.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique AppID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Create Metadata Objects ===&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
*content: identify content stream&lt;br /&gt;
*ad: identify each ad&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required/Obligatory&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isAudio || indicate measurement of audio ads or audio content || &amp;lt;code&amp;gt;&amp;quot;true&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset (64 character limit)|| custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program ||(string) name of program (254 character limit) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title ||(string) episode title (max 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; ('86400' for 24/7 Livestream if only one assetid is used for the whole stream. If reporting on program level, length of the program. ) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear over-the-air broadcast || Supported formats are:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS+xx:xx&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS-xx:xx&lt;br /&gt;
&lt;br /&gt;
YYYYMMDDHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
MM-DD-YYYY&lt;br /&gt;
&lt;br /&gt;
MM/DD/YYYY&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| scheduledEndDate || the airdate when this particular asset ended in the linear over-the-air broadcast || should be same format as airdate || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches over-the-air ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || ✓&lt;br /&gt;
|-&lt;br /&gt;
| stationType	|| OTA station flag and/or OTA station type&lt;br /&gt;
||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; Custom station built per user&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; OTA streaming station with the same adload&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; OTA station with a different ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;3&amp;quot;&amp;lt;/code&amp;gt; Multicast eRadio or online station&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;4&amp;quot;&amp;lt;/code&amp;gt; On Demand Audio(podcasting)	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| stationId	|| (string) name of the channel || custom||✓&lt;br /&gt;
|-&lt;br /&gt;
| clientid	|| &lt;br /&gt;
parent ID – value is automatically populated through provided App ID.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to override the brand configured to the App ID, pass parent &amp;lt;br/&amp;gt;&lt;br /&gt;
value here and the sub-brand ID associated to that brand in the subbrand &amp;lt;br/&amp;gt;&lt;br /&gt;
key (e.g. multiple brands in App)	&lt;br /&gt;
||&lt;br /&gt;
provided by Nielsen	&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| vcid	|| vcid/sub-brand ID – value is automatically populated through provided&amp;lt;br/&amp;gt;&lt;br /&gt;
App ID. In order to override the sub-brand configured to the App ID, value can &amp;lt;br/&amp;gt;&lt;br /&gt;
be passed here (e.g. multiple sub-brands in App). clientId does not need to be provided.&lt;br /&gt;
||&lt;br /&gt;
provided by Nielsen	&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| progen	|| (string) genre information (max 254 characters) &lt;br /&gt;
||&lt;br /&gt;
custom	&lt;br /&gt;
||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example Content Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var content_metadata_object = {  &lt;br /&gt;
  // SDK&lt;br /&gt;
  type:     'content',&lt;br /&gt;
  isAudio:   true,&lt;br /&gt;
  assetid:  'VID123-123456',&lt;br /&gt;
  program:  'program name',&lt;br /&gt;
  title:    'episode title',&lt;br /&gt;
  length:   '543',&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example Ad Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: 'AD-1',&lt;br /&gt;
  type:    'preroll'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt; 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. &amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Avoid Carriage Return (CR) and/or Linefeeds (LF) in all fields (because of current data reporting as CSV)!&lt;br /&gt;
Implementations has to filter out CR/LF with appropriate programming.&lt;br /&gt;
It's also a good idea to check and validate entries from other systems (eg. CMS, player) before simply copy them to the variables in metadata.&lt;br /&gt;
&lt;br /&gt;
== Interrupt Scenarios ==&lt;br /&gt;
&lt;br /&gt;
=== Pause Event ===&lt;br /&gt;
To indicate pause&lt;br /&gt;
&lt;br /&gt;
* Call [[stop]] immediately and withhold sending playhead position.&lt;br /&gt;
* Start sending pings – [[loadMetadata]] and [[playheadPosition]] - once the playback resumes.&lt;br /&gt;
&lt;br /&gt;
=== Other Interrupt Scenarios ===&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var stopped = false;&lt;br /&gt;
function closePlayer() {&lt;br /&gt;
	if (stopped) {return;}&lt;br /&gt;
	stopped = true;&lt;br /&gt;
	if (inMidroll) {    // Only inside a midroll indicate &amp;lt;stop&amp;gt; for the ad&lt;br /&gt;
		nSdkInstance.ggPM('stop', playheadPositionMidroll);&lt;br /&gt;
	}&lt;br /&gt;
	nSdkInstance.ggPM('end', playheadPositionContent);    // Indicate &amp;lt;end&amp;gt; for the content&lt;br /&gt;
};&lt;br /&gt;
window.addEventListener(&amp;quot;beforeunload&amp;quot;, function (e) {&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
window.addEventListener(&amp;quot;pagehide&amp;quot;, function (e) {	// for iOS mobile &amp;quot;pagehide&amp;quot; recommended by apple&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is ggPM().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
nSdkInstance.ggPM('event', parameter);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event name !! Values to pass !!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 'loadMetadata'	|| content/ad metadata object	|| Needs to be called at the beginning of each content/ad metadata object&lt;br /&gt;
|-&lt;br /&gt;
| 'setPlayheadPosition'&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;on-demoand (or ad ): || current position in seconds (integer) &amp;lt;br/&amp;gt;&lt;br /&gt;
*&amp;quot;Live: current UTC timestamp (seconds since January 1st 1970)&amp;lt;br/&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
Pass playhead position every second during playback&lt;br /&gt;
|-&lt;br /&gt;
| 'stop' ||	playhead position in seconds	|| Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| 'end'	|| playhead position in seconds	|| This event has to be called once for the current asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Playhead position as integer&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' has to be called every second&lt;br /&gt;
&lt;br /&gt;
==== Example Events ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass ( Object ):''' Content Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', contentMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass  ( Object ):''' Pre-roll AD Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', prerollMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' setPlayheadPosition  |  '''Value Pass ( Integer ):''' playheadPosition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' stop  |  '''Value Pass ( Integer ):''' stopPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('stop', stopPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' end  |  '''Value Pass ( Integer ):''' endPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('end', endPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==  SDK Event Lifecycle ==&lt;br /&gt;
&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle without ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:even browser no ads.png]]&lt;br /&gt;
&lt;br /&gt;
==== Example without ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);  // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle with ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:event browser.png|event browser.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example with ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// PREROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end pre-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);&lt;br /&gt;
&lt;br /&gt;
// MIDROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
  &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end mid-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); &lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// POSTROLL&lt;br /&gt;
nSdkInstance.ggPM('loadmetadata', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); // end post-roll stream&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
* 'setPlayheadPosition' is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling 'stop', 'end', or 'loadmetadata'.&lt;br /&gt;
&lt;br /&gt;
* after an 'end' in case there is a new content played, there is a need to have another 'loadmetadata' again.&lt;br /&gt;
&lt;br /&gt;
* For Ad, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
* When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
* For pre-roll ads you have to call the loadMetadata event for content at the start of stream and after the preroll&lt;br /&gt;
&lt;br /&gt;
== Nielsen Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/de/de/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click &amp;quot;Choices&amp;quot; to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen Online Measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/de/de/optout.html.''&lt;br /&gt;
&lt;br /&gt;
====Opt Back In====&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'debug'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
&lt;br /&gt;
====Example Production Initialization Call ====&lt;br /&gt;
Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;, &amp;quot;myPlayerName&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': before going live you have to inform Nielsen - this is necessary, because Nielsen team has to adjust internal configuration parameter to enable data collection. Without that notification no data will be collected and no data will be reported.&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Norway_Audio_App_SDK&amp;diff=2794</id>
		<title>DCR Norway Audio App SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Norway_Audio_App_SDK&amp;diff=2794"/>
		<updated>2018-06-06T10:16:23Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen software development kit (SDK) is one of multiple frameworks that Nielsen provides to enable measuring linear (live) and on-demand audio and video viewing using desktop computers, mobile devices, OTT devices, etc.&lt;br /&gt;
The App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK:''' The Nielsen SDK package contains a variety of sample players for your reference.&lt;br /&gt;
If you do not have any of these prerequisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] guide for information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
==  Implementation ==&lt;br /&gt;
This guide covers implementation steps for iOS using Xcode and Android using Android Studio.&lt;br /&gt;
&lt;br /&gt;
== Setting up your  Development Environment  ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
xCode|&lt;br /&gt;
&amp;lt;big&amp;gt;&lt;br /&gt;
'''Configuring Xcode Development Environment''' &lt;br /&gt;
&amp;lt;/big&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 9.0 and above.&lt;br /&gt;
&lt;br /&gt;
The SDK uses the NSURLSession instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': All communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Importing Frameworks'''&amp;lt;/big&amp;gt;&lt;br /&gt;
The first step is to ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework &lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Swift'''&amp;lt;/big&amp;gt;&lt;br /&gt;
To import a set of Objective-C files in the same app target as your Swift code, you rely on an Objective-C bridging header to expose those files to Swift. Xcode offers to create this header file when you add a Swift file to an existing Objective-C app, or an Objective-C file to an existing Swift app.&lt;br /&gt;
&lt;br /&gt;
Select File/New File/Objective-C File  &amp;lt;br /&amp;gt;&lt;br /&gt;
Xcode will prompt you to create a bridging header.&lt;br /&gt;
[[File:bridgingheader 2x.png|600px|center|link=]] &amp;lt;br /&amp;gt;&lt;br /&gt;
Once this file has been created, you need to add the following:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Objective-C'''&amp;lt;/big&amp;gt;&lt;br /&gt;
Add the code &lt;br /&gt;
&amp;lt;syntaxhighlight lang =&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 to the View Controller’s header file.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
|Android =&lt;br /&gt;
&amp;lt;big&amp;gt;'''Configuring Android Development Environment'''&amp;lt;/big&amp;gt;'&lt;br /&gt;
*The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package.&lt;br /&gt;
&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Library'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Classes/package&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== SDK Initialization ==&lt;br /&gt;
The latest version of the Nielsen App SDK allows instantiating multiple instances of the SDK object, which can be used simultaneously without any issue. The sharedInstance API that creates a singleton object was deprecated prior to version 5.1.1. (Version 4.0 for Android)&lt;br /&gt;
&lt;br /&gt;
* A maximum of four SDK instances per appid are supported. When a fifth SDK instance is launched, the SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
* When four SDK instances exist, you must destroy an old instance before creating a new one.&lt;br /&gt;
&lt;br /&gt;
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.&lt;br /&gt;
&lt;br /&gt;
* The appid is provided by the Nielsen Technical Account Manager (TAM). The appid is a GUID data type and is specific to the application.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter / Argument !! Description !! Source !! Required/Obligatory? !! Example&lt;br /&gt;
|-&lt;br /&gt;
| appid || Unique id for the application assigned by Nielsen. It is GUID data type.|| Nielsen-specified || ✓ || PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&lt;br /&gt;
|-&lt;br /&gt;
| appversion || Release version of the client app. Not needed anymore.|| custom ||  || 0.1.1&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Nielsen collection facility to which the SDK should connect.&lt;br /&gt;
'''Norway RAM integrations'''&lt;br /&gt;
* &amp;quot;nor&amp;quot;&lt;br /&gt;
|| Nielsen-specified || ✓ || &amp;quot;nor&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || Enables Nielsen console logging. Only required for testing&lt;br /&gt;
|| Nielsen-specified || required until cretification/going live || &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==== Sample SDK Initialization Code ====&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift  = &lt;br /&gt;
Swift 4.0 Example:&lt;br /&gt;
&amp;lt;code&amp;gt;NielsenInit.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
           &amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;nor&amp;quot;,&lt;br /&gt;
            &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sample code using AVPlayer.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ViewController.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class ViewController: UIViewController, NielsenAppApiDelegate, AVPictureInPictureControllerDelegate, CLLocationManagerDelegate  {&lt;br /&gt;
    &lt;br /&gt;
    let avPlayerViewController = AVPlayerViewController()&lt;br /&gt;
    var avPlayer:AVPlayer?&lt;br /&gt;
    var nielsenAppApi: NielsenAppApi!&lt;br /&gt;
&lt;br /&gt;
    override func viewDidLoad() {&lt;br /&gt;
        super.viewDidLoad()&lt;br /&gt;
&lt;br /&gt;
        self.nielsenAppApi = NielsenInit.createNielsenAppApi(delegate: self)&lt;br /&gt;
        NSLog(&amp;quot;Nielsen SDK initialized&amp;quot;)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Objective C = &lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;    &lt;br /&gt;
#import &amp;quot;NlsAppApiFactory.h&amp;quot;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@implementation NlsAppApiFactory&lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
{&lt;br /&gt;
    NSDictionary *appInformation = @{&lt;br /&gt;
                                     @&amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;sfcode&amp;quot;: &amp;quot;nor&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot;&lt;br /&gt;
                                     };&lt;br /&gt;
    return [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&lt;br /&gt;
}&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following would be the &amp;lt;code&amp;gt;NlsAppApiFactory.h&amp;lt;/code&amp;gt; file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@class NielsenAppApi;&lt;br /&gt;
@protocol NielsenAppApiDeligate;&lt;br /&gt;
&lt;br /&gt;
@interface NlsAppApiFactory : NSObject &lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppAPI *) createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;nor&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;DEBUG&amp;quot;); // only for debug builds&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&amp;lt;br /&amp;gt;&lt;br /&gt;
* Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== APP SDK Error &amp;amp; Event Codes ==&lt;br /&gt;
To view the Error and Event codes for iOS and Android, please review the [[APP SDK Event Codes|App SDK Event Code]] Reference page.&lt;br /&gt;
== Configure Payload ==&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift = &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
let channelInfo = [&lt;br /&gt;
    &amp;quot;channelName&amp;quot;: &amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
        &lt;br /&gt;
let contentMetadata = [&lt;br /&gt;
    &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
    &amp;quot;isAudio&amp;quot;: &amp;quot;true&amp;quot;,&lt;br /&gt;
    &amp;quot;assetid&amp;quot;: &amp;quot;88675545&amp;quot;,&lt;br /&gt;
    &amp;quot;title&amp;quot;: &amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
    &amp;quot;isfullepisode&amp;quot;: &amp;quot;n&amp;quot;,&lt;br /&gt;
    &amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
    &amp;quot;program&amp;quot;: &amp;quot;Program Name&amp;quot;,&lt;br /&gt;
    &amp;quot;length&amp;quot;: &amp;quot;3600&amp;quot;, &lt;br /&gt;
    &amp;quot;airdate&amp;quot;: &amp;quot;20171020 10:05:00&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;     &lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt; &lt;br /&gt;
NSDictionary  *channelInfo = @{&lt;br /&gt;
    @&amp;quot;channelName&amp;quot;:@&amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
NSDictionary *contentMetadata = @{&lt;br /&gt;
    @&amp;quot;type&amp;quot;: @&amp;quot;content&amp;quot;,&lt;br /&gt;
    @&amp;quot;isAudio&amp;quot;: @&amp;quot;true&amp;quot;,&lt;br /&gt;
    @&amp;quot;assetid&amp;quot;: [NSString stringWithFormat:@&amp;quot;ProgramAssetId-%d&amp;quot;, i],&lt;br /&gt;
    @&amp;quot;length&amp;quot;: @&amp;quot;3600&amp;quot;,&lt;br /&gt;
    @&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;,&lt;br /&gt;
    @&amp;quot;title&amp;quot;: @&amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
    @&amp;quot;isfullepisode&amp;quot;: @&amp;quot;y&amp;quot;,&lt;br /&gt;
    @&amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
    @&amp;quot;airdate&amp;quot;: &amp;quot;20161013 20:00:00&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject channelInfo = new JSONObject()&lt;br /&gt;
    .put(&amp;quot;channelname&amp;quot;, &amp;quot;My Channel Name 1&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
JSONObject contentMetadata = new JSONObject()&lt;br /&gt;
//SDK Metadata&lt;br /&gt;
    .put(&amp;quot;type&amp;quot;, &amp;quot;content&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;isAudio&amp;quot;, &amp;quot;true&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;assetid&amp;quot;, &amp;quot;vid345-67483&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;title&amp;quot;, &amp;quot;Program S3, EP1&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;length&amp;quot;, &amp;quot;3600&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;isfullepisode&amp;quot;, &amp;quot;y&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;adloadtype&amp;quot;, &amp;quot;2&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;airdate&amp;quot;, &amp;quot;20161013 20:00:00&amp;quot;)&lt;br /&gt;
  &amp;lt;/syntaxhighlight&amp;gt;   &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Configure metadata === &lt;br /&gt;
When starting a streaming session a channel info metadata object needs to be passed to the SDK containing a channelName. The name should remain constant throughout the completion of an episode or live stream.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| channelName	|| Any string representing the channel/stream	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Content metadata ===&lt;br /&gt;
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required/Obligatory&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isAudio || indicate measurement of audio ads or audio content || &amp;lt;code&amp;gt;&amp;quot;true&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset (64 character limit)|| custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program ||(string) name of program (254 character limit) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title ||(string) episode title (max 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; ('86400' for 24/7 Livestream if only one assetid is used for the whole stream. If reporting on program level, length of the program. For Event-Livestreams planned length. For on-demand stream length) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear over-the-air broadcast || Supported formats are:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS+xx:xx&lt;br /&gt;
&lt;br /&gt;
YYYY-MM-DDTHH:MI:SS-xx:xx&lt;br /&gt;
&lt;br /&gt;
YYYYMMDDHH:MI:SS&lt;br /&gt;
&lt;br /&gt;
MM-DD-YYYY&lt;br /&gt;
&lt;br /&gt;
MM/DD/YYYY &lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| scheduledEndDate || the airdate when this particular asset ended in the linear over-the-air broadcast || should be same format as airdate || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches over-the-air ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || ✓&lt;br /&gt;
|-&lt;br /&gt;
| stationType	|| OTA station flag and/or OTA station type&lt;br /&gt;
||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; Custom station built per user&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; OTA streaming station with the same adload&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; OTA station with a different ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;3&amp;quot;&amp;lt;/code&amp;gt; Multicast eRadio or online station&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;4&amp;quot;&amp;lt;/code&amp;gt; On Demand Audio(podcasting)	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| stationId	|| (string) name of the channel || custom||✓&lt;br /&gt;
|-&lt;br /&gt;
| clientid	|| &lt;br /&gt;
parent ID – value is automatically populated through provided App ID.&amp;lt;br/&amp;gt;&lt;br /&gt;
In order to override the brand configured to the App ID, pass parent &amp;lt;br/&amp;gt;&lt;br /&gt;
value here and the sub-brand ID associated to that brand in the subbrand &amp;lt;br/&amp;gt;&lt;br /&gt;
key (e.g. multiple brands in App)	&lt;br /&gt;
||&lt;br /&gt;
provided by Nielsen	&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| vcid	|| vcid/sub-brand ID – value is automatically populated through provided&amp;lt;br/&amp;gt;&lt;br /&gt;
App ID. In order to override the sub-brand configured to the App ID, value can &amp;lt;br/&amp;gt;&lt;br /&gt;
be passed here (e.g. multiple sub-brands in App). clientId does not need to be provided.&lt;br /&gt;
||&lt;br /&gt;
provided by Nielsen	&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| progen	|| (string) genre information (max 254 characters) &lt;br /&gt;
||&lt;br /&gt;
custom	&lt;br /&gt;
||&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
The ad metadata (if applicable) should be passed for each individual ad, if ads are available during or before the stream begins.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Configure API Calls ==&lt;br /&gt;
=== Sample API Sequence ===&lt;br /&gt;
A Sample API sequence could follow this flow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
|On App Start||&amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadata];&amp;lt;/code&amp;gt; || // contentMetadata Object contains the JSON metadata for the impression&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;[nielsenMeter play: channelInfo];&amp;lt;/code&amp;gt; || // channelInfo contains JSON metadata of channel name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadataObject];&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;[nielsenMeter end];&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Life cycle of SDK instance ===&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[play]] and [[loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## &amp;lt;code&amp;gt;appDisableApi&amp;lt;/code&amp;gt; is called&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (assign) BOOL appDisableApi;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[play]], [[loadMetadata]] and  [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== API Call sequence ===&lt;br /&gt;
==== Use Case 1: Content has no Advertisements ====&lt;br /&gt;
Call [[play()]] with channelName JSON as below.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
   &amp;quot;channelName&amp;quot;: &amp;quot;My Channel Name 1&amp;quot;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Call [[loadMetadata()]] with JSON metadata for content as below.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
  &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
  &amp;quot;isAudio&amp;quot;: &amp;quot;true&amp;quot;,&lt;br /&gt;
  &amp;quot;assetid&amp;quot;: &amp;quot;stream345-67483&amp;quot;,&lt;br /&gt;
  &amp;quot;program&amp;quot;: &amp;quot;ProgramName&amp;quot;,&lt;br /&gt;
  &amp;quot;title&amp;quot;: &amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
  &amp;quot;length&amp;quot;: &amp;quot;3600&amp;quot;,&lt;br /&gt;
  ...&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Call [[setPlayheadPosition()]] every one second until a pause / stop.&lt;br /&gt;
Use the sample API sequence below as a reference to identify the specific events that need to be called during content playback without ads.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;mAppSdk.play(channelInfo); &amp;lt;/code&amp;gt; || // channelInfo contains JSON metadata of channel name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.loadMetadata(contentMetaDataObject);&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // position is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;mAppSdk.end();&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Use Case 2: Content has Advertisements ====&lt;br /&gt;
Call [[play()]] with channelName JSON as below.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
   &amp;quot;channelName&amp;quot;: &amp;quot;My Channel Name 1&amp;quot;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Call [[loadMetadata()]] with JSON metadata for ad as below.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;json&amp;quot;&amp;gt;{&lt;br /&gt;
   &amp;quot;type&amp;quot;: &amp;quot;preroll&amp;quot;,&lt;br /&gt;
   &amp;quot;assetid&amp;quot;: &amp;quot;ad=123&amp;quot;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Note: In case the individual ad details are not available, send ad pod (presence) details through the [[loadMetadata]] and playhead position through [[playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Call [[setPlayheadPosition()]] every one second until a pause / stop / another [[loadMetadata()]] is called. Playhead should be passed for the entire duration of ad pod, if the ad pod details are passed as part of [[loadMetadata()]].&lt;br /&gt;
&lt;br /&gt;
The sample API sequence can be used as a reference to identify the specific events that need to be called during content and ad playback.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;mAppSdk.play(channelInfo); &amp;lt;/code&amp;gt; || // channelName contains JSON metadata of channel name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.loadMetadata(contentMetaDataObject);&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | Preroll || &amp;lt;code&amp;gt;mAppSdk.loadMetadata(prerollMetadataObject);&amp;lt;/code&amp;gt; || // prerollMetadataObject contains the JSON metadata for the preroll ad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // position is position of the playhead while the preroll ad is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.stop();&amp;lt;/code&amp;gt; || // Call stop after preroll occurs&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | Content || &amp;lt;code&amp;gt;mAppSdk.loadMetadata(contentMetaDataObject);&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // position is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.stop();&amp;lt;/code&amp;gt; || // Call stop after the content is paused (ad starts)&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;6&amp;quot; | Midroll || &amp;lt;code&amp;gt;mAppSdk.loadMetadata(midrollMetaDataObject);&amp;lt;/code&amp;gt; || // midrollMetadataObject contains the JSON metadata for the midroll ad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // position is position of the playhead while the midroll ad is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.stop();&amp;lt;/code&amp;gt; || // App moves to background(midroll pauses) &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.loadMetadata(midrollMetaDataObject);&amp;lt;/code&amp;gt; || // App moves to foreground (midroll resumes) &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the midroll ad is being played &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.stop();&amp;lt;/code&amp;gt; || // Call stop after midroll occurs&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | Content (End of stream) || &amp;lt;code&amp;gt;mAppSdk.loadMetadata(contentMetaDataObject);&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // position is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.stop();&amp;lt;/code&amp;gt; || // Always call stop irrespective of postroll is followed or not&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;mAppSdk.end();&amp;lt;/code&amp;gt; || // Call end() at the end of content&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | Postroll || &amp;lt;code&amp;gt;mAppSdk.loadMetadata(postrollMetaDataObject);&amp;lt;/code&amp;gt; || // postrollMetadataObject contains the JSON metadata for the postroll ad&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.setPlayheadPosition(playheadPosition);&amp;lt;/code&amp;gt; || // position is position of the playhead while the postroll ad is being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;mAppSdk.stop();&amp;lt;/code&amp;gt; || // Call stop after postroll occurs&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Note: Each Ad playhead should reset or begin from 0 at ad start. When content has resumed following an ad break, playhead position must continue from where previous content segment was left off.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence of Calls ===&lt;br /&gt;
&lt;br /&gt;
=== play ===&lt;br /&gt;
Use [[play]] to pass the channel information containing the channelName parameter when the streaming session starts.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt; - (void)play:(id)channelInfo;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;nielsenAppApi?.play(channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
The loadMetadata function is used to inform the SDK about new content. The contentMetadata object passed in should contain the values as described above.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void)loadMetadata:(id)contentMetadata;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void loadMetadata(JSONObject contentMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.loadMetadata(contentMetadata)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== playheadPosition ===&lt;br /&gt;
Use playheadPosition to tell the SDK about the current position in the stream. For live content this should be the UTC timestamp in seconds, for on-demand content simply the second in the stream.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void) playheadPosition: (long long) playheadPos;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Sending playheadposition for content ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
AVPlayer *player;&lt;br /&gt;
CMTime curTime=[player currentTime];&lt;br /&gt;
int pos = CMTimeGetSeconds(curTime);&lt;br /&gt;
[nAppApiObject playheadPosition:pos];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
        //Monitor the Playhead position of the AVPlayer&lt;br /&gt;
        let timeInterval: CMTime = CMTimeMakeWithSeconds(1.0,10)&lt;br /&gt;
        self.avPlayerViewController.player?.addPeriodicTimeObserver(forInterval: timeInterval, queue: DispatchQueue.main) {(elapsedTime: CMTime) -&amp;gt; Void in&lt;br /&gt;
            if self.avPlayerViewController.player!.currentItem?.status == .readyToPlay {&lt;br /&gt;
                let time : Float64 = self.avPlayerViewController.player!.currentTime().seconds;&lt;br /&gt;
                let pos = Int64(time);&lt;br /&gt;
                NSLog(&amp;quot;New Elapse Time = \(time)&amp;quot;);&lt;br /&gt;
                self.nielsenAppApi?.playheadPosition(pos);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void setPlayheadPosition(long position);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== stop ===&lt;br /&gt;
Tell the SDK that content playback has stopped.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void) stop;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== end ===&lt;br /&gt;
When content stop is initiated and content cannot be resumed from the same position. For example when the stream has reached its end or in situations where it can only be restarted from the beginning.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;- (void) end;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void end();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.end();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Interruptions during playback ==&lt;br /&gt;
As part of integrating Nielsen App SDK with the player application, the Audio / Video app developer needs to handle the following possible interruption scenarios:&lt;br /&gt;
* Pause / Play&lt;br /&gt;
* Network Loss (Wi-Fi / Airplane / Cellular)&lt;br /&gt;
* Call Interrupt (SIM or Third party Skype / Hangout call)&lt;br /&gt;
* Alarm Interrupt&lt;br /&gt;
* Content Buffering&lt;br /&gt;
* Device Lock / Unlock (For Audio players only if audio stops playing)&lt;br /&gt;
* App going in the Background/Foreground (For Audio players only if audio stops playing)&lt;br /&gt;
* Channel / Station Change Scenario&lt;br /&gt;
* Unplugging of headphone&lt;br /&gt;
In case of encountering one of the above interruptions, the player application needs to&lt;br /&gt;
* Call [[stop]] immediately (except when content is buffering) and withhold sending playhead position.&lt;br /&gt;
* Start sending pings – [[loadMetadata]] and [[playheadPosition]] for the new viewing session, once the playback resumes.&lt;br /&gt;
Please see the [[Digital Measurement FAQ]] for more details&lt;br /&gt;
&lt;br /&gt;
== Privacy and Opt-Out ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
&lt;br /&gt;
iOS| &lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to the page referenced by the opt-out url provided by the SDK. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL for the Nielsen Privacy web page should be retrieved from the optOutURL property of the SDK object &amp;lt;code&amp;gt;optOutURL&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL in the optOutURL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- === Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = nAppApiObject.optOutURL;&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:App optout en1.png|link=]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Android = &lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to page referenced by the opt-out url provided by the SDK. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking &amp;lt;code&amp;gt;userOptOutURLString()&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public String userOptOutURLString()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the &amp;lt;code&amp;gt; getOptOutStatus() &amp;lt;/code&amp;gt; method.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean getOptOutStatus()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy App.png|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
*SDK will be sending the data pings to census even though the user opted out. However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make one update to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_devDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;iOS Example:&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
            &amp;quot;appid&amp;quot;: &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;nor&amp;quot;&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Android Example:&amp;lt;/big&amp;gt;''' &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;nor&amp;quot;)&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': before going live you have to inform Nielsen team - this is necessary, because Nielsen team has to adjust internal configuration parameter to enable data collection. Without that notification no data will be collected and no data will be reported.&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_React_Native_Integration&amp;diff=2710</id>
		<title>DCR React Native Integration</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_React_Native_Integration&amp;diff=2710"/>
		<updated>2018-05-08T08:32:52Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: /* SDK Initialization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
This guide will show how to use the Nielsen SDK in React Native applications on Android and iOS devices. We will not go into detail about what React Native is or how to create Apps with this Framework. If you are looking for information on this, please read the [http://facebook.github.io/react-native/ React-Native] documentation.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK:''' The Nielsen SDK package contains a variety of sample players for your reference.&lt;br /&gt;
If you do not have any of these prerequisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] guide for information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
For more detail on the native SDKs please refer to the App integration guides available on this portal.&lt;br /&gt;
&lt;br /&gt;
==  Implementation ==&lt;br /&gt;
This guide covers implementation covers&lt;br /&gt;
&lt;br /&gt;
* the implementation of React-Native bridges for iOS and Android&lt;br /&gt;
* the usage of the exposed Javascript API&lt;br /&gt;
&lt;br /&gt;
What we will not cover is the general setup of React-Native applications. If you are new to React-Native please refer to [https://facebook.github.io/react-native/ React-Native] for documentation.&lt;br /&gt;
&lt;br /&gt;
For simplicity we have focused on implementing a single instance of the Nielsen SDK. Should there be the need for multiple instances developers have to add some logic for that.&lt;br /&gt;
&lt;br /&gt;
== Setting up your Environment  ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;section-container auto&amp;quot; data-section&amp;gt;&lt;br /&gt;
  &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;iOS&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first step is to ensure that the following frameworks and libraries are imported into the Frameworks folder of the iOS Xcode project before working with the Nielsen SDK.&lt;br /&gt;
&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
&lt;br /&gt;
Nielsens App SDK is compatible with Apple iOS versions 9.0 and above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; &lt;br /&gt;
  &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;Android&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
The first step is to add the AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine to the libs folder (might have to be created) for the Android part of your project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;android/app/libs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next step is to add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Library'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Classes/package&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Creating React-Native bridges for the Nielsen SDK ==&lt;br /&gt;
In order to be able to use Nielsens native SDKs React-Native bridges have to be implemented and added to the iOS and Android projects. The following shows implementations for both platforms, that provide the basic methods to start measuring the app. The source code can be copied from below to provide an easy start.&lt;br /&gt;
&lt;br /&gt;
Please refer to the integration guides for Nielsens native SDKs to get a deeper understanding of the technical detail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;section-container auto&amp;quot; data-section&amp;gt;&lt;br /&gt;
  &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;iOS&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The iOS implementation of the bridge module consists of two files, a header and an implementation file, written in Objective-c. These two files need to be added to the iOS XCode project.&lt;br /&gt;
&lt;br /&gt;
The header file is &amp;lt;code&amp;gt;NielsenReactBridge.h&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
// Copyright &amp;lt;2018&amp;gt; &amp;lt;The Nielsen Company&amp;gt;&lt;br /&gt;
// &lt;br /&gt;
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files&lt;br /&gt;
// (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,&lt;br /&gt;
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is&lt;br /&gt;
// furnished to do so, subject to the following conditions:&lt;br /&gt;
// &lt;br /&gt;
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
// &lt;br /&gt;
// THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES&lt;br /&gt;
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE&lt;br /&gt;
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR&lt;br /&gt;
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;br /&gt;
&lt;br /&gt;
#import &amp;lt;React/RCTBridgeModule.h&amp;gt;&lt;br /&gt;
#import &amp;lt;React/RCTEventEmitter.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@interface NielsenReactBridge : RCTEventEmitter &amp;lt;RCTBridgeModule&amp;gt;&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The actual implementation of the module happens in &amp;lt;code&amp;gt;NielsenReactBridge.m&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
// Copyright &amp;lt;2018&amp;gt; &amp;lt;The Nielsen Company&amp;gt;&lt;br /&gt;
// &lt;br /&gt;
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files&lt;br /&gt;
// (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,&lt;br /&gt;
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is&lt;br /&gt;
// furnished to do so, subject to the following conditions:&lt;br /&gt;
// &lt;br /&gt;
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
// &lt;br /&gt;
// THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES&lt;br /&gt;
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE&lt;br /&gt;
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR&lt;br /&gt;
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;br /&gt;
&lt;br /&gt;
#import &amp;quot;NielsenReactBridge.h&amp;quot;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
static NSString *const TAG = @&amp;quot;NielsenReactBridge&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
@interface NielsenReactBridge() &amp;lt;NielsenAppApiDelegate&amp;gt;&lt;br /&gt;
@property (strong) NielsenAppApi* nlsSDk;&lt;br /&gt;
@end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@implementation NielsenReactBridge&lt;br /&gt;
RCT_EXPORT_MODULE();&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Since we need to communicate the opt-out url to javascript via events&lt;br /&gt;
 * we need to implement the following method&lt;br /&gt;
 */&lt;br /&gt;
- (NSArray&amp;lt;NSString *&amp;gt; *)supportedEvents&lt;br /&gt;
{&lt;br /&gt;
  return @[@&amp;quot;OptOutUrl&amp;quot;];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * A logging helper method&lt;br /&gt;
 */&lt;br /&gt;
void NLSLog(NSString* tag, NSString* format, ...)&lt;br /&gt;
{&lt;br /&gt;
  va_list argList;&lt;br /&gt;
  va_start(argList, format);&lt;br /&gt;
  NSLog(@&amp;quot;%@&amp;quot;, [[NSString alloc] initWithFormat:[NSString stringWithFormat:@&amp;quot;[%@]: %@&amp;quot;, tag, format] arguments: argList]);&lt;br /&gt;
  va_end(argList);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Init creates the SDK instance and passes on the provided metadata.&lt;br /&gt;
 * appInfo is simply passed to initWithAppInfo since the SDK already &lt;br /&gt;
 * performs error checking&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(init:(NSDictionary *)appInfo)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;init called with metadat '%@''&amp;quot;, appInfo);&lt;br /&gt;
&lt;br /&gt;
  if (!self.nlsSDk) {&lt;br /&gt;
    self.nlsSDk= [[NielsenAppApi alloc] initWithAppInfo:appInfo delegate:self];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's play method. The provided metadata is &lt;br /&gt;
 * simply passed on&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(play:(NSDictionary *)channelInfo)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;play called with metadata '%@'&amp;quot;, channelInfo);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk play:channelInfo];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's loadMetadata method. The provided contentMetaData is &lt;br /&gt;
 * simply passed on&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(loadMetadata:(NSDictionary *)contentMetaData)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;loadMetadata called with '%@'&amp;quot;, contentMetaData);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk loadMetadata:contentMetaData];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's setPlayheadPosition method. The provided playhead is &lt;br /&gt;
 * simply passed on to the SDK&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(setPlayheadPosition:(nonnull NSNumber *)ph)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;setHeadPosition called with '%@'&amp;quot;,ph);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk playheadPosition:[ph longLongValue]];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's stop method. &lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(stop)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;stop called&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk stop];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's end method. &lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(end)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;end called&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk end];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * optOutUrl retrieves the url from the SDK instance and fires off the&lt;br /&gt;
 * OptOutUrl event, so the url can be captured&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(optOutUrl)&lt;br /&gt;
{&lt;br /&gt;
  [self sendEventWithName:@&amp;quot;OptOutUrl&amp;quot; body:@{@&amp;quot;url&amp;quot;: self.nlsSDk.optOutURL}];&lt;br /&gt;
}&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; &lt;br /&gt;
  &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;Android&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Android implementation of the bridge module consists of two files, an implementation of a NielsenPackage to announce the actual module and the implementation of NielsenReactBridge itself. The implementations have been put into the Java package&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com.nielsen.app.react&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The package implementation is in &amp;lt;code&amp;gt;com/nielsen/app/react/NielsenPackage.java&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// Copyright &amp;lt;2018&amp;gt; &amp;lt;The Nielsen Company&amp;gt;&lt;br /&gt;
// &lt;br /&gt;
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files&lt;br /&gt;
// (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,&lt;br /&gt;
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is&lt;br /&gt;
// furnished to do so, subject to the following conditions:&lt;br /&gt;
// &lt;br /&gt;
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
// &lt;br /&gt;
// THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES&lt;br /&gt;
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE&lt;br /&gt;
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR&lt;br /&gt;
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;br /&gt;
&lt;br /&gt;
package com.nielsen.app.react;&lt;br /&gt;
&lt;br /&gt;
import com.facebook.react.bridge.NativeModule;&lt;br /&gt;
import com.facebook.react.bridge.ReactApplicationContext;&lt;br /&gt;
import com.facebook.react.ReactPackage;&lt;br /&gt;
import com.facebook.react.uimanager.ViewManager;&lt;br /&gt;
import com.nielsen.app.react.NielsenReactBridge;&lt;br /&gt;
import java.util.ArrayList;&lt;br /&gt;
import java.util.Collections;&lt;br /&gt;
import java.util.List;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 */&lt;br /&gt;
public class NielsenPackage implements ReactPackage {&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Override createNativeModules to return our bridge module&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public List&amp;lt;NativeModule&amp;gt; createNativeModules(ReactApplicationContext reactContext) {&lt;br /&gt;
        List&amp;lt;NativeModule&amp;gt; modules = new ArrayList&amp;lt;&amp;gt;();&lt;br /&gt;
        modules.add(new NielsenReactBridge(reactContext));&lt;br /&gt;
&lt;br /&gt;
        return modules;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
    */&lt;br /&gt;
    @Override&lt;br /&gt;
    public List&amp;lt;ViewManager&amp;gt; createViewManagers(ReactApplicationContext reactContext) {&lt;br /&gt;
        return Collections.emptyList();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com/nielsen/app/react/NielsenReactBridge.java&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// Copyright &amp;lt;2018&amp;gt; &amp;lt;The Nielsen Company&amp;gt;&lt;br /&gt;
// &lt;br /&gt;
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files&lt;br /&gt;
// (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,&lt;br /&gt;
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is&lt;br /&gt;
// furnished to do so, subject to the following conditions:&lt;br /&gt;
// &lt;br /&gt;
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
// &lt;br /&gt;
// THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES&lt;br /&gt;
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE&lt;br /&gt;
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR&lt;br /&gt;
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;br /&gt;
&lt;br /&gt;
package com.nielsen.app.react;&lt;br /&gt;
&lt;br /&gt;
import android.util.Log;&lt;br /&gt;
import com.facebook.react.bridge.LifecycleEventListener;&lt;br /&gt;
import com.facebook.react.bridge.ReactApplicationContext;&lt;br /&gt;
import com.facebook.react.bridge.ReactContextBaseJavaModule;&lt;br /&gt;
import com.facebook.react.modules.core.DeviceEventManagerModule;&lt;br /&gt;
import com.facebook.react.bridge.ReactMethod;&lt;br /&gt;
import com.facebook.react.bridge.ReadableMap;&lt;br /&gt;
import com.facebook.react.bridge.WritableMap;&lt;br /&gt;
import com.facebook.react.bridge.Arguments;&lt;br /&gt;
import com.facebook.react.bridge.ReadableMapKeySetIterator;&lt;br /&gt;
import com.nielsen.app.sdk.AppSdk;&lt;br /&gt;
import com.nielsen.app.sdk.IAppNotifier;&lt;br /&gt;
import com.nielsen.app.sdk.AppLaunchMeasurementManager;&lt;br /&gt;
import org.json.JSONObject;&lt;br /&gt;
import org.json.JSONException;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * NielsenReactBridge is the class briding between react JS code&lt;br /&gt;
 * and the native Nielsen SDK.&lt;br /&gt;
 */&lt;br /&gt;
public class NielsenReactBridge extends ReactContextBaseJavaModule &lt;br /&gt;
                                implements IAppNotifier, LifecycleEventListener {&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
    */&lt;br /&gt;
    private static final String NIELSEN_TAG = &amp;quot;NielsenReactBridge&amp;quot;;&lt;br /&gt;
    private AppSdk mAppSdk = null; // the AppSdk main object&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Constructor for the NielsenReactBridge&lt;br /&gt;
     * Adds the new instance as LifeCycleEventListener for conttex&lt;br /&gt;
     * @param context  The react application context&lt;br /&gt;
     */&lt;br /&gt;
    public NielsenReactBridge(ReactApplicationContext context) {&lt;br /&gt;
        super(context);&lt;br /&gt;
        context.addLifecycleEventListener(this);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements getName method from ReactContextBaseJavaModule&lt;br /&gt;
     * @return  The constant string 'NielsenReactBridge'&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public String getName() {&lt;br /&gt;
        return &amp;quot;NielsenReactBridge&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements getName method from IAppNotifier&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onAppSdkEvent(long l, int i, String s) {}&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Initializes the module for use &lt;br /&gt;
     * @param obj   An instance of ReadableMap (mapped JS object) containing&lt;br /&gt;
     *              initialization meta data&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void init(final ReadableMap obj) {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG, &amp;quot;Called init&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        if (null == mAppSdk) {&lt;br /&gt;
            try {&lt;br /&gt;
                JSONObject appSdkConfig = readableMapToJSONObject(obj);&lt;br /&gt;
                mAppSdk = new AppSdk(getReactApplicationContext(), appSdkConfig, this);&lt;br /&gt;
                if (!mAppSdk.isValid())&lt;br /&gt;
                {&lt;br /&gt;
                    Log.e(NIELSEN_TAG, &amp;quot;SDK Init failed&amp;quot;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch(Exception ex) {&lt;br /&gt;
            }   &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Static method to convert ReadableMap instances to JSONObject instances&lt;br /&gt;
     * (used by the Nielsen SDK)&lt;br /&gt;
     * @param obj   The ReadableMap instance to be converted&lt;br /&gt;
     * @return      An instance of JSONObject containing the mapped JS object&lt;br /&gt;
     *              values (if successful, empty otherwise) &lt;br /&gt;
     */&lt;br /&gt;
    static private JSONObject readableMapToJSONObject(final ReadableMap obj) {&lt;br /&gt;
&lt;br /&gt;
        JSONObject ret = new JSONObject();&lt;br /&gt;
&lt;br /&gt;
        try {&lt;br /&gt;
            ReadableMapKeySetIterator it = obj.keySetIterator();&lt;br /&gt;
            while (it.hasNextKey()) {&lt;br /&gt;
                String key = it.nextKey();&lt;br /&gt;
                ret.put(key, obj.getDynamic(key).asString());&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        catch (JSONException ex) {&lt;br /&gt;
            Log.e(NIELSEN_TAG, ex.getMessage());&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return ret;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK play method. Simply forwards calls &lt;br /&gt;
     * to the SDK.&lt;br /&gt;
     * @param obj   ReadableMap instance containing the mapped JS meta&lt;br /&gt;
     *              data object, e.g. {channelName: 'channel name here'}&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void play(final ReadableMap obj) {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG, &amp;quot;Called play &amp;quot; + obj.toString());&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            JSONObject playObject = readableMapToJSONObject(obj);&lt;br /&gt;
            mAppSdk.play(playObject);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK loadMetadata method. Simply forwards calls &lt;br /&gt;
     * to the SDK.&lt;br /&gt;
     * @param obj   ReadableMap instance containing the mapped JS meta&lt;br /&gt;
     *              data object&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void loadMetadata(final ReadableMap obj) {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called loadMetadata&amp;quot;);&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            JSONObject contentMetadata = readableMapToJSONObject(obj);&lt;br /&gt;
            mAppSdk.loadMetadata(contentMetadata);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK setPlayheadPosition method. Simply &lt;br /&gt;
     * forwards calls to the SDK.&lt;br /&gt;
     * @param ph    The current playhead position&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void setPlayheadPosition(final Double ph) {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called setPlayHeadPosition: &amp;quot; + &amp;quot; &amp;quot; + ph);&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            mAppSdk.setPlayheadPosition(ph.longValue());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK stop method. Simply &lt;br /&gt;
     * forwards calls to the SDK.&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void stop() {&lt;br /&gt;
        Log.d(NIELSEN_TAG, &amp;quot;Called stop&amp;quot;);&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            mAppSdk.stop();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK end method. Simply &lt;br /&gt;
     * forwards calls to the SDK.&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void end() {&lt;br /&gt;
        &lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called end&amp;quot;);&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            mAppSdk.end();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper to retrieve the optOutUrl from the Nielsen SDK. &lt;br /&gt;
     * Emits a &amp;quot;OptOutUrl&amp;quot; event with the url as payload.&lt;br /&gt;
     * Needs to be catched in JS&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void optOutUrl() {&lt;br /&gt;
&lt;br /&gt;
        WritableMap params = Arguments.createMap();&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            params.putString(&amp;quot;url&amp;quot;, mAppSdk.userOptOutURLString());&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        getReactApplicationContext()&lt;br /&gt;
        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)&lt;br /&gt;
        .emit(&amp;quot;OptOutUrl&amp;quot;, params);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements LifecycleEventListener's onHostResume method.&lt;br /&gt;
     * Uses AppLaunchMeasurementManager.appInForeground to notify SDK about&lt;br /&gt;
     * app coming to foreground again&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onHostResume() {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called onHostResume&amp;quot;);&lt;br /&gt;
        AppLaunchMeasurementManager.appInForeground(getReactApplicationContext());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements LifecycleEventListener's onHostPause method.&lt;br /&gt;
     * Uses AppLaunchMeasurementManager.appInBackground to notify SDK about&lt;br /&gt;
     * app going to background&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onHostPause() {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called onHostPause&amp;quot;);&lt;br /&gt;
        AppLaunchMeasurementManager.appInBackground(getReactApplicationContext());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements LifecycleEventListener's onHostDestroy method.&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onHostDestroy() {&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called onHostDestroy&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The package needs to be provided in the getPackages method of the MainApplication.java file. This file exists under the android folder in your react-native application directory. The path to this file is: android/app/src/main/java/com/your-app-name/MainApplication.java.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
import com.nielsen.app.react.NielsenPackage;   //&amp;lt;-- Import the package in MainApplication.java&lt;br /&gt;
//...&lt;br /&gt;
&lt;br /&gt;
    protected List&amp;lt;ReactPackage&amp;gt; getPackages() {&lt;br /&gt;
        return Arrays.&amp;lt;ReactPackage&amp;gt;asList(&lt;br /&gt;
                //...,&lt;br /&gt;
                new NielsenPackage()); // &amp;lt;-- Add the bridge package to the getPackages method.&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In order to import the bridges into the Javascript context, create a file&lt;br /&gt;
&amp;lt;code&amp;gt;NielsenModule.js&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import { NativeModules } from 'react-native'&lt;br /&gt;
&lt;br /&gt;
export default NativeModules.NielsenReactBridge&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SDK Initialization ==&lt;br /&gt;
The bridge implementations above allow the usage of one instance of the Nielsen App SDK. The latest version of the Nielsen App SDK allows instantiating multiple instances of the SDK object, which can be used simultaneously without any issue. For more information on this please read the relevant App SDK Guide.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.&lt;br /&gt;
&lt;br /&gt;
* The appid is provided by the Nielsen Technical Account Manager (TAM). The appid is a GUID data type and is specific to the application.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter / Argument !! Description !! Source !! Required? !! Example&lt;br /&gt;
|-&lt;br /&gt;
| appid || Unique id for the application assigned by Nielsen. It is GUID data type.|| Nielsen-specified || Yes || PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&lt;br /&gt;
|-&lt;br /&gt;
| appname || Name of the application || Client-defined || No|| Nielsen Sample App&lt;br /&gt;
|-&lt;br /&gt;
| appversion || Current version of the app used || Client-defined || No || &amp;quot;1.0.2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Nielsen collection facility to which the SDK should connect.&lt;br /&gt;
'''Italian Clients'''&lt;br /&gt;
* &amp;quot;it&amp;quot;&lt;br /&gt;
|| Nielsen-specified || Yes || &amp;quot;it&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || Enables Nielsen console logging. Only required for testing&lt;br /&gt;
|| Nielsen-specified || While not live || &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Sample SDK Initialization Code ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
    import NielsenModule from './NielsenModule';&lt;br /&gt;
&lt;br /&gt;
    let appInformation = {&amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
                          &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
                          &amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot;};&lt;br /&gt;
   NielsenModule.init(appInformation);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== APP SDK Error &amp;amp; Event Codes ==&lt;br /&gt;
To view the Error and Event codes for iOS and Android, please review the [[APP SDK Event Codes|App SDK Event Code]] Reference page.&lt;br /&gt;
&lt;br /&gt;
== Configure Payload ==&lt;br /&gt;
All metadata is passed to the bridges in form of objects containing the in the following described properties. An example metadata object could look like&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
let metadata = {&lt;br /&gt;
    'type':'content',&lt;br /&gt;
    'assetid':'asset12345',&lt;br /&gt;
    'program':'My Program',&lt;br /&gt;
    'title':'My Title',&lt;br /&gt;
    'length':'42',&lt;br /&gt;
    'airdate':'20180302 16:32:00',&lt;br /&gt;
    'isfullepisode':'n',&lt;br /&gt;
    'adloadtype':'2'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The following section will explain the different values.&lt;br /&gt;
&lt;br /&gt;
=== Configure metadata === &lt;br /&gt;
Configure metadata should remain constant throughout the completion of an episode or live stream.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| channelName	|| Any string representing the channel/stream	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Content metadata ===&lt;br /&gt;
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset || custom &amp;lt;br&amp;gt;(no [[Special Characters]]) || Yes&lt;br /&gt;
|-&lt;br /&gt;
| program ||name of program (25 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| title ||name of program (40 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || Yes&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear TV; if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || YYYYMMDD HH24:MI:SS || Yes&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || Yes&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches TV ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || Yes&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
The ad metadata (if applicable) should be passed for each individual ad, if ads are available during or before the stream begins.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Static Measurement ===&lt;br /&gt;
The Nielsen SDK is able to monitor Application launch events and how long your app has been running. Once the Nielsen module has been Initialized, pass a metadata object to loadMeta data that follows these rules: &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Data Type !! Value !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type || asset type || fixed || &amp;lt;code&amp;gt;'static'&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID for each article || dynamic || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| 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&lt;br /&gt;
|}&lt;br /&gt;
You only need to do this once upon app start.&lt;br /&gt;
&lt;br /&gt;
== Configure API Calls ==&lt;br /&gt;
=== Sample API Sequence ===&lt;br /&gt;
A Sample API sequence could follow this flow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
|On App Start||&amp;lt;code&amp;gt;NielsenModule.loadMetadata(contentMetadata);&amp;lt;/code&amp;gt; || // contentMetadata Object contains the JSON metadata for the impression&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;NielsenModule.play(channelName);&amp;lt;/code&amp;gt; || // channelName contains JSON metadata of channel/video name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NielsenModule.loadMetadata(contentMetadataObject);&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;NielsenModule.playheadPosition(position);&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;NielsenModule.end();&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
=== Life cycle of SDK instance ===&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[DCR_Video_APP_SDK#play|play]] and [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[DCR_Video_APP_SDK#stop|stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[DCR_Video_APP_SDK#end|end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] and  [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence of Calls ===&lt;br /&gt;
=== play ===&lt;br /&gt;
Use the play function to pass the channel descriptor information through channelName parameter when the user taps the '''Play''' button on the player.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.play(channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
The loadMetadata function is used to inform the SDK about new content. The contentMetadata object passed in should contain the values as described above.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.loadMetadata(contentMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== playheadPosition ===&lt;br /&gt;
Use playheadPosition to tell the SDK about the current position in the video. For live content this should be the UTC timestamp in seconds, for on-demand content simply the second in the video.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.playheadPosition(playheadPos);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== stop ===&lt;br /&gt;
Tell the SDK that content playback has stopped.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.stop();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== end ===&lt;br /&gt;
When content stop is initiated and content cannot be resumed from the same position (it can only be restarted from the beginning of stream).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.end();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Privacy and Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL for the Nielsen Privacy web page should be retrieved from via the &amp;lt;code&amp;gt;optOutURL()&amp;lt;/code&amp;gt; method of the SDK bridge and opened in 'WebView' / External browser.&lt;br /&gt;
*If the returned value is null or empty, handle the exception gracefully and retry later.&lt;br /&gt;
&lt;br /&gt;
Due to the limitation that native methods can't return values directly, the URL will be sent to the Javascript context as &amp;quot;OptOutUrl&amp;quot; event, with the url as the payload.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
    const nielsen = new NativeEventEmitter(NielsenModule);&lt;br /&gt;
    &lt;br /&gt;
    const subscription = nielsen.addListener(&lt;br /&gt;
      'OptOutUrl',&lt;br /&gt;
      (data) =&amp;gt; { &lt;br /&gt;
         //display data.url&lt;br /&gt;
      }&lt;br /&gt;
    );&lt;br /&gt;
    NielsenModule.optOutUrl();&lt;br /&gt;
   //...&lt;br /&gt;
   subscription.remove(); // do not forget to unsubscribe&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make one update to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_devDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Example:&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
    let appInformation = {&lt;br /&gt;
            &amp;quot;appid&amp;quot;: &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
    };&lt;br /&gt;
    NielsenModule.init(appInformation);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_React_Native_Integration&amp;diff=2709</id>
		<title>DCR React Native Integration</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_React_Native_Integration&amp;diff=2709"/>
		<updated>2018-05-08T08:32:12Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: /* Sample SDK Initialization Code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
This guide will show how to use the Nielsen SDK in React Native applications on Android and iOS devices. We will not go into detail about what React Native is or how to create Apps with this Framework. If you are looking for information on this, please read the [http://facebook.github.io/react-native/ React-Native] documentation.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK:''' The Nielsen SDK package contains a variety of sample players for your reference.&lt;br /&gt;
If you do not have any of these prerequisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] guide for information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
For more detail on the native SDKs please refer to the App integration guides available on this portal.&lt;br /&gt;
&lt;br /&gt;
==  Implementation ==&lt;br /&gt;
This guide covers implementation covers&lt;br /&gt;
&lt;br /&gt;
* the implementation of React-Native bridges for iOS and Android&lt;br /&gt;
* the usage of the exposed Javascript API&lt;br /&gt;
&lt;br /&gt;
What we will not cover is the general setup of React-Native applications. If you are new to React-Native please refer to [https://facebook.github.io/react-native/ React-Native] for documentation.&lt;br /&gt;
&lt;br /&gt;
For simplicity we have focused on implementing a single instance of the Nielsen SDK. Should there be the need for multiple instances developers have to add some logic for that.&lt;br /&gt;
&lt;br /&gt;
== Setting up your Environment  ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;section-container auto&amp;quot; data-section&amp;gt;&lt;br /&gt;
  &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;iOS&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first step is to ensure that the following frameworks and libraries are imported into the Frameworks folder of the iOS Xcode project before working with the Nielsen SDK.&lt;br /&gt;
&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
&lt;br /&gt;
Nielsens App SDK is compatible with Apple iOS versions 9.0 and above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; &lt;br /&gt;
  &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;Android&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
The first step is to add the AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine to the libs folder (might have to be created) for the Android part of your project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;android/app/libs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next step is to add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Library'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Classes/package&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Creating React-Native bridges for the Nielsen SDK ==&lt;br /&gt;
In order to be able to use Nielsens native SDKs React-Native bridges have to be implemented and added to the iOS and Android projects. The following shows implementations for both platforms, that provide the basic methods to start measuring the app. The source code can be copied from below to provide an easy start.&lt;br /&gt;
&lt;br /&gt;
Please refer to the integration guides for Nielsens native SDKs to get a deeper understanding of the technical detail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;section-container auto&amp;quot; data-section&amp;gt;&lt;br /&gt;
  &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;iOS&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The iOS implementation of the bridge module consists of two files, a header and an implementation file, written in Objective-c. These two files need to be added to the iOS XCode project.&lt;br /&gt;
&lt;br /&gt;
The header file is &amp;lt;code&amp;gt;NielsenReactBridge.h&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
// Copyright &amp;lt;2018&amp;gt; &amp;lt;The Nielsen Company&amp;gt;&lt;br /&gt;
// &lt;br /&gt;
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files&lt;br /&gt;
// (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,&lt;br /&gt;
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is&lt;br /&gt;
// furnished to do so, subject to the following conditions:&lt;br /&gt;
// &lt;br /&gt;
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
// &lt;br /&gt;
// THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES&lt;br /&gt;
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE&lt;br /&gt;
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR&lt;br /&gt;
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;br /&gt;
&lt;br /&gt;
#import &amp;lt;React/RCTBridgeModule.h&amp;gt;&lt;br /&gt;
#import &amp;lt;React/RCTEventEmitter.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@interface NielsenReactBridge : RCTEventEmitter &amp;lt;RCTBridgeModule&amp;gt;&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The actual implementation of the module happens in &amp;lt;code&amp;gt;NielsenReactBridge.m&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
// Copyright &amp;lt;2018&amp;gt; &amp;lt;The Nielsen Company&amp;gt;&lt;br /&gt;
// &lt;br /&gt;
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files&lt;br /&gt;
// (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,&lt;br /&gt;
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is&lt;br /&gt;
// furnished to do so, subject to the following conditions:&lt;br /&gt;
// &lt;br /&gt;
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
// &lt;br /&gt;
// THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES&lt;br /&gt;
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE&lt;br /&gt;
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR&lt;br /&gt;
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;br /&gt;
&lt;br /&gt;
#import &amp;quot;NielsenReactBridge.h&amp;quot;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
static NSString *const TAG = @&amp;quot;NielsenReactBridge&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
@interface NielsenReactBridge() &amp;lt;NielsenAppApiDelegate&amp;gt;&lt;br /&gt;
@property (strong) NielsenAppApi* nlsSDk;&lt;br /&gt;
@end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@implementation NielsenReactBridge&lt;br /&gt;
RCT_EXPORT_MODULE();&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Since we need to communicate the opt-out url to javascript via events&lt;br /&gt;
 * we need to implement the following method&lt;br /&gt;
 */&lt;br /&gt;
- (NSArray&amp;lt;NSString *&amp;gt; *)supportedEvents&lt;br /&gt;
{&lt;br /&gt;
  return @[@&amp;quot;OptOutUrl&amp;quot;];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * A logging helper method&lt;br /&gt;
 */&lt;br /&gt;
void NLSLog(NSString* tag, NSString* format, ...)&lt;br /&gt;
{&lt;br /&gt;
  va_list argList;&lt;br /&gt;
  va_start(argList, format);&lt;br /&gt;
  NSLog(@&amp;quot;%@&amp;quot;, [[NSString alloc] initWithFormat:[NSString stringWithFormat:@&amp;quot;[%@]: %@&amp;quot;, tag, format] arguments: argList]);&lt;br /&gt;
  va_end(argList);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Init creates the SDK instance and passes on the provided metadata.&lt;br /&gt;
 * appInfo is simply passed to initWithAppInfo since the SDK already &lt;br /&gt;
 * performs error checking&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(init:(NSDictionary *)appInfo)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;init called with metadat '%@''&amp;quot;, appInfo);&lt;br /&gt;
&lt;br /&gt;
  if (!self.nlsSDk) {&lt;br /&gt;
    self.nlsSDk= [[NielsenAppApi alloc] initWithAppInfo:appInfo delegate:self];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's play method. The provided metadata is &lt;br /&gt;
 * simply passed on&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(play:(NSDictionary *)channelInfo)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;play called with metadata '%@'&amp;quot;, channelInfo);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk play:channelInfo];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's loadMetadata method. The provided contentMetaData is &lt;br /&gt;
 * simply passed on&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(loadMetadata:(NSDictionary *)contentMetaData)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;loadMetadata called with '%@'&amp;quot;, contentMetaData);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk loadMetadata:contentMetaData];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's setPlayheadPosition method. The provided playhead is &lt;br /&gt;
 * simply passed on to the SDK&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(setPlayheadPosition:(nonnull NSNumber *)ph)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;setHeadPosition called with '%@'&amp;quot;,ph);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk playheadPosition:[ph longLongValue]];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's stop method. &lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(stop)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;stop called&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk stop];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's end method. &lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(end)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;end called&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk end];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * optOutUrl retrieves the url from the SDK instance and fires off the&lt;br /&gt;
 * OptOutUrl event, so the url can be captured&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(optOutUrl)&lt;br /&gt;
{&lt;br /&gt;
  [self sendEventWithName:@&amp;quot;OptOutUrl&amp;quot; body:@{@&amp;quot;url&amp;quot;: self.nlsSDk.optOutURL}];&lt;br /&gt;
}&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; &lt;br /&gt;
  &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;Android&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Android implementation of the bridge module consists of two files, an implementation of a NielsenPackage to announce the actual module and the implementation of NielsenReactBridge itself. The implementations have been put into the Java package&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com.nielsen.app.react&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The package implementation is in &amp;lt;code&amp;gt;com/nielsen/app/react/NielsenPackage.java&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// Copyright &amp;lt;2018&amp;gt; &amp;lt;The Nielsen Company&amp;gt;&lt;br /&gt;
// &lt;br /&gt;
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files&lt;br /&gt;
// (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,&lt;br /&gt;
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is&lt;br /&gt;
// furnished to do so, subject to the following conditions:&lt;br /&gt;
// &lt;br /&gt;
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
// &lt;br /&gt;
// THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES&lt;br /&gt;
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE&lt;br /&gt;
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR&lt;br /&gt;
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;br /&gt;
&lt;br /&gt;
package com.nielsen.app.react;&lt;br /&gt;
&lt;br /&gt;
import com.facebook.react.bridge.NativeModule;&lt;br /&gt;
import com.facebook.react.bridge.ReactApplicationContext;&lt;br /&gt;
import com.facebook.react.ReactPackage;&lt;br /&gt;
import com.facebook.react.uimanager.ViewManager;&lt;br /&gt;
import com.nielsen.app.react.NielsenReactBridge;&lt;br /&gt;
import java.util.ArrayList;&lt;br /&gt;
import java.util.Collections;&lt;br /&gt;
import java.util.List;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 */&lt;br /&gt;
public class NielsenPackage implements ReactPackage {&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Override createNativeModules to return our bridge module&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public List&amp;lt;NativeModule&amp;gt; createNativeModules(ReactApplicationContext reactContext) {&lt;br /&gt;
        List&amp;lt;NativeModule&amp;gt; modules = new ArrayList&amp;lt;&amp;gt;();&lt;br /&gt;
        modules.add(new NielsenReactBridge(reactContext));&lt;br /&gt;
&lt;br /&gt;
        return modules;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
    */&lt;br /&gt;
    @Override&lt;br /&gt;
    public List&amp;lt;ViewManager&amp;gt; createViewManagers(ReactApplicationContext reactContext) {&lt;br /&gt;
        return Collections.emptyList();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com/nielsen/app/react/NielsenReactBridge.java&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// Copyright &amp;lt;2018&amp;gt; &amp;lt;The Nielsen Company&amp;gt;&lt;br /&gt;
// &lt;br /&gt;
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files&lt;br /&gt;
// (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,&lt;br /&gt;
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is&lt;br /&gt;
// furnished to do so, subject to the following conditions:&lt;br /&gt;
// &lt;br /&gt;
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
// &lt;br /&gt;
// THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES&lt;br /&gt;
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE&lt;br /&gt;
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR&lt;br /&gt;
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;br /&gt;
&lt;br /&gt;
package com.nielsen.app.react;&lt;br /&gt;
&lt;br /&gt;
import android.util.Log;&lt;br /&gt;
import com.facebook.react.bridge.LifecycleEventListener;&lt;br /&gt;
import com.facebook.react.bridge.ReactApplicationContext;&lt;br /&gt;
import com.facebook.react.bridge.ReactContextBaseJavaModule;&lt;br /&gt;
import com.facebook.react.modules.core.DeviceEventManagerModule;&lt;br /&gt;
import com.facebook.react.bridge.ReactMethod;&lt;br /&gt;
import com.facebook.react.bridge.ReadableMap;&lt;br /&gt;
import com.facebook.react.bridge.WritableMap;&lt;br /&gt;
import com.facebook.react.bridge.Arguments;&lt;br /&gt;
import com.facebook.react.bridge.ReadableMapKeySetIterator;&lt;br /&gt;
import com.nielsen.app.sdk.AppSdk;&lt;br /&gt;
import com.nielsen.app.sdk.IAppNotifier;&lt;br /&gt;
import com.nielsen.app.sdk.AppLaunchMeasurementManager;&lt;br /&gt;
import org.json.JSONObject;&lt;br /&gt;
import org.json.JSONException;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * NielsenReactBridge is the class briding between react JS code&lt;br /&gt;
 * and the native Nielsen SDK.&lt;br /&gt;
 */&lt;br /&gt;
public class NielsenReactBridge extends ReactContextBaseJavaModule &lt;br /&gt;
                                implements IAppNotifier, LifecycleEventListener {&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
    */&lt;br /&gt;
    private static final String NIELSEN_TAG = &amp;quot;NielsenReactBridge&amp;quot;;&lt;br /&gt;
    private AppSdk mAppSdk = null; // the AppSdk main object&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Constructor for the NielsenReactBridge&lt;br /&gt;
     * Adds the new instance as LifeCycleEventListener for conttex&lt;br /&gt;
     * @param context  The react application context&lt;br /&gt;
     */&lt;br /&gt;
    public NielsenReactBridge(ReactApplicationContext context) {&lt;br /&gt;
        super(context);&lt;br /&gt;
        context.addLifecycleEventListener(this);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements getName method from ReactContextBaseJavaModule&lt;br /&gt;
     * @return  The constant string 'NielsenReactBridge'&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public String getName() {&lt;br /&gt;
        return &amp;quot;NielsenReactBridge&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements getName method from IAppNotifier&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onAppSdkEvent(long l, int i, String s) {}&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Initializes the module for use &lt;br /&gt;
     * @param obj   An instance of ReadableMap (mapped JS object) containing&lt;br /&gt;
     *              initialization meta data&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void init(final ReadableMap obj) {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG, &amp;quot;Called init&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        if (null == mAppSdk) {&lt;br /&gt;
            try {&lt;br /&gt;
                JSONObject appSdkConfig = readableMapToJSONObject(obj);&lt;br /&gt;
                mAppSdk = new AppSdk(getReactApplicationContext(), appSdkConfig, this);&lt;br /&gt;
                if (!mAppSdk.isValid())&lt;br /&gt;
                {&lt;br /&gt;
                    Log.e(NIELSEN_TAG, &amp;quot;SDK Init failed&amp;quot;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch(Exception ex) {&lt;br /&gt;
            }   &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Static method to convert ReadableMap instances to JSONObject instances&lt;br /&gt;
     * (used by the Nielsen SDK)&lt;br /&gt;
     * @param obj   The ReadableMap instance to be converted&lt;br /&gt;
     * @return      An instance of JSONObject containing the mapped JS object&lt;br /&gt;
     *              values (if successful, empty otherwise) &lt;br /&gt;
     */&lt;br /&gt;
    static private JSONObject readableMapToJSONObject(final ReadableMap obj) {&lt;br /&gt;
&lt;br /&gt;
        JSONObject ret = new JSONObject();&lt;br /&gt;
&lt;br /&gt;
        try {&lt;br /&gt;
            ReadableMapKeySetIterator it = obj.keySetIterator();&lt;br /&gt;
            while (it.hasNextKey()) {&lt;br /&gt;
                String key = it.nextKey();&lt;br /&gt;
                ret.put(key, obj.getDynamic(key).asString());&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        catch (JSONException ex) {&lt;br /&gt;
            Log.e(NIELSEN_TAG, ex.getMessage());&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return ret;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK play method. Simply forwards calls &lt;br /&gt;
     * to the SDK.&lt;br /&gt;
     * @param obj   ReadableMap instance containing the mapped JS meta&lt;br /&gt;
     *              data object, e.g. {channelName: 'channel name here'}&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void play(final ReadableMap obj) {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG, &amp;quot;Called play &amp;quot; + obj.toString());&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            JSONObject playObject = readableMapToJSONObject(obj);&lt;br /&gt;
            mAppSdk.play(playObject);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK loadMetadata method. Simply forwards calls &lt;br /&gt;
     * to the SDK.&lt;br /&gt;
     * @param obj   ReadableMap instance containing the mapped JS meta&lt;br /&gt;
     *              data object&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void loadMetadata(final ReadableMap obj) {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called loadMetadata&amp;quot;);&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            JSONObject contentMetadata = readableMapToJSONObject(obj);&lt;br /&gt;
            mAppSdk.loadMetadata(contentMetadata);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK setPlayheadPosition method. Simply &lt;br /&gt;
     * forwards calls to the SDK.&lt;br /&gt;
     * @param ph    The current playhead position&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void setPlayheadPosition(final Double ph) {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called setPlayHeadPosition: &amp;quot; + &amp;quot; &amp;quot; + ph);&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            mAppSdk.setPlayheadPosition(ph.longValue());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK stop method. Simply &lt;br /&gt;
     * forwards calls to the SDK.&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void stop() {&lt;br /&gt;
        Log.d(NIELSEN_TAG, &amp;quot;Called stop&amp;quot;);&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            mAppSdk.stop();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK end method. Simply &lt;br /&gt;
     * forwards calls to the SDK.&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void end() {&lt;br /&gt;
        &lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called end&amp;quot;);&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            mAppSdk.end();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper to retrieve the optOutUrl from the Nielsen SDK. &lt;br /&gt;
     * Emits a &amp;quot;OptOutUrl&amp;quot; event with the url as payload.&lt;br /&gt;
     * Needs to be catched in JS&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void optOutUrl() {&lt;br /&gt;
&lt;br /&gt;
        WritableMap params = Arguments.createMap();&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            params.putString(&amp;quot;url&amp;quot;, mAppSdk.userOptOutURLString());&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        getReactApplicationContext()&lt;br /&gt;
        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)&lt;br /&gt;
        .emit(&amp;quot;OptOutUrl&amp;quot;, params);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements LifecycleEventListener's onHostResume method.&lt;br /&gt;
     * Uses AppLaunchMeasurementManager.appInForeground to notify SDK about&lt;br /&gt;
     * app coming to foreground again&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onHostResume() {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called onHostResume&amp;quot;);&lt;br /&gt;
        AppLaunchMeasurementManager.appInForeground(getReactApplicationContext());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements LifecycleEventListener's onHostPause method.&lt;br /&gt;
     * Uses AppLaunchMeasurementManager.appInBackground to notify SDK about&lt;br /&gt;
     * app going to background&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onHostPause() {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called onHostPause&amp;quot;);&lt;br /&gt;
        AppLaunchMeasurementManager.appInBackground(getReactApplicationContext());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements LifecycleEventListener's onHostDestroy method.&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onHostDestroy() {&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called onHostDestroy&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The package needs to be provided in the getPackages method of the MainApplication.java file. This file exists under the android folder in your react-native application directory. The path to this file is: android/app/src/main/java/com/your-app-name/MainApplication.java.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
import com.nielsen.app.react.NielsenPackage;   //&amp;lt;-- Import the package in MainApplication.java&lt;br /&gt;
//...&lt;br /&gt;
&lt;br /&gt;
    protected List&amp;lt;ReactPackage&amp;gt; getPackages() {&lt;br /&gt;
        return Arrays.&amp;lt;ReactPackage&amp;gt;asList(&lt;br /&gt;
                //...,&lt;br /&gt;
                new NielsenPackage()); // &amp;lt;-- Add the bridge package to the getPackages method.&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In order to import the bridges into the Javascript context, create a file&lt;br /&gt;
&amp;lt;code&amp;gt;NielsenModule.js&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import { NativeModules } from 'react-native'&lt;br /&gt;
&lt;br /&gt;
export default NativeModules.NielsenReactBridge&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SDK Initialization ==&lt;br /&gt;
The bridge implementations above allow the usage of one instance of the Nielsen App SDK. The latest version of the Nielsen App SDK allows instantiating multiple instances of the SDK object, which can be used simultaneously without any issue. For more information on this please read the relevant App SDK Guide.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.&lt;br /&gt;
&lt;br /&gt;
* The appid is provided by the Nielsen Technical Account Manager (TAM). The appid is a GUID data type and is specific to the application.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter / Argument !! Description !! Source !! Required? !! Example&lt;br /&gt;
|-&lt;br /&gt;
| appid || Unique id for the application assigned by Nielsen. It is GUID data type.|| Nielsen-specified || Yes || PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&lt;br /&gt;
|-&lt;br /&gt;
| appname || Name of the application || Client-defined || No|| Nielsen Sample App&lt;br /&gt;
|-&lt;br /&gt;
| appversion || Current version of the app used || Client-defined || No || &amp;quot;1.0.2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Nielsen collection facility to which the SDK should connect.&lt;br /&gt;
'''Italian Clients'''&lt;br /&gt;
* &amp;quot;it&amp;quot;&lt;br /&gt;
|| Nielsen-specified || Yes || &amp;quot;it&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || Enables Nielsen console logging. Only required for testing&lt;br /&gt;
|| Nielsen-specified || Optional || &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Sample SDK Initialization Code ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
    import NielsenModule from './NielsenModule';&lt;br /&gt;
&lt;br /&gt;
    let appInformation = {&amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
                          &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
                          &amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot;};&lt;br /&gt;
   NielsenModule.init(appInformation);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== APP SDK Error &amp;amp; Event Codes ==&lt;br /&gt;
To view the Error and Event codes for iOS and Android, please review the [[APP SDK Event Codes|App SDK Event Code]] Reference page.&lt;br /&gt;
&lt;br /&gt;
== Configure Payload ==&lt;br /&gt;
All metadata is passed to the bridges in form of objects containing the in the following described properties. An example metadata object could look like&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
let metadata = {&lt;br /&gt;
    'type':'content',&lt;br /&gt;
    'assetid':'asset12345',&lt;br /&gt;
    'program':'My Program',&lt;br /&gt;
    'title':'My Title',&lt;br /&gt;
    'length':'42',&lt;br /&gt;
    'airdate':'20180302 16:32:00',&lt;br /&gt;
    'isfullepisode':'n',&lt;br /&gt;
    'adloadtype':'2'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The following section will explain the different values.&lt;br /&gt;
&lt;br /&gt;
=== Configure metadata === &lt;br /&gt;
Configure metadata should remain constant throughout the completion of an episode or live stream.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| channelName	|| Any string representing the channel/stream	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Content metadata ===&lt;br /&gt;
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset || custom &amp;lt;br&amp;gt;(no [[Special Characters]]) || Yes&lt;br /&gt;
|-&lt;br /&gt;
| program ||name of program (25 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| title ||name of program (40 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || Yes&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear TV; if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || YYYYMMDD HH24:MI:SS || Yes&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || Yes&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches TV ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || Yes&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
The ad metadata (if applicable) should be passed for each individual ad, if ads are available during or before the stream begins.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Static Measurement ===&lt;br /&gt;
The Nielsen SDK is able to monitor Application launch events and how long your app has been running. Once the Nielsen module has been Initialized, pass a metadata object to loadMeta data that follows these rules: &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Data Type !! Value !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type || asset type || fixed || &amp;lt;code&amp;gt;'static'&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID for each article || dynamic || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| 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&lt;br /&gt;
|}&lt;br /&gt;
You only need to do this once upon app start.&lt;br /&gt;
&lt;br /&gt;
== Configure API Calls ==&lt;br /&gt;
=== Sample API Sequence ===&lt;br /&gt;
A Sample API sequence could follow this flow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
|On App Start||&amp;lt;code&amp;gt;NielsenModule.loadMetadata(contentMetadata);&amp;lt;/code&amp;gt; || // contentMetadata Object contains the JSON metadata for the impression&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;NielsenModule.play(channelName);&amp;lt;/code&amp;gt; || // channelName contains JSON metadata of channel/video name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NielsenModule.loadMetadata(contentMetadataObject);&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;NielsenModule.playheadPosition(position);&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;NielsenModule.end();&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
=== Life cycle of SDK instance ===&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[DCR_Video_APP_SDK#play|play]] and [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[DCR_Video_APP_SDK#stop|stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[DCR_Video_APP_SDK#end|end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] and  [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence of Calls ===&lt;br /&gt;
=== play ===&lt;br /&gt;
Use the play function to pass the channel descriptor information through channelName parameter when the user taps the '''Play''' button on the player.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.play(channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
The loadMetadata function is used to inform the SDK about new content. The contentMetadata object passed in should contain the values as described above.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.loadMetadata(contentMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== playheadPosition ===&lt;br /&gt;
Use playheadPosition to tell the SDK about the current position in the video. For live content this should be the UTC timestamp in seconds, for on-demand content simply the second in the video.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.playheadPosition(playheadPos);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== stop ===&lt;br /&gt;
Tell the SDK that content playback has stopped.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.stop();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== end ===&lt;br /&gt;
When content stop is initiated and content cannot be resumed from the same position (it can only be restarted from the beginning of stream).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.end();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Privacy and Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL for the Nielsen Privacy web page should be retrieved from via the &amp;lt;code&amp;gt;optOutURL()&amp;lt;/code&amp;gt; method of the SDK bridge and opened in 'WebView' / External browser.&lt;br /&gt;
*If the returned value is null or empty, handle the exception gracefully and retry later.&lt;br /&gt;
&lt;br /&gt;
Due to the limitation that native methods can't return values directly, the URL will be sent to the Javascript context as &amp;quot;OptOutUrl&amp;quot; event, with the url as the payload.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
    const nielsen = new NativeEventEmitter(NielsenModule);&lt;br /&gt;
    &lt;br /&gt;
    const subscription = nielsen.addListener(&lt;br /&gt;
      'OptOutUrl',&lt;br /&gt;
      (data) =&amp;gt; { &lt;br /&gt;
         //display data.url&lt;br /&gt;
      }&lt;br /&gt;
    );&lt;br /&gt;
    NielsenModule.optOutUrl();&lt;br /&gt;
   //...&lt;br /&gt;
   subscription.remove(); // do not forget to unsubscribe&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make one update to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_devDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Example:&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
    let appInformation = {&lt;br /&gt;
            &amp;quot;appid&amp;quot;: &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
    };&lt;br /&gt;
    NielsenModule.init(appInformation);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_React_Native_Integration&amp;diff=2708</id>
		<title>DCR React Native Integration</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_React_Native_Integration&amp;diff=2708"/>
		<updated>2018-05-08T08:31:21Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: /* Going Live */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
This guide will show how to use the Nielsen SDK in React Native applications on Android and iOS devices. We will not go into detail about what React Native is or how to create Apps with this Framework. If you are looking for information on this, please read the [http://facebook.github.io/react-native/ React-Native] documentation.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK:''' The Nielsen SDK package contains a variety of sample players for your reference.&lt;br /&gt;
If you do not have any of these prerequisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] guide for information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
For more detail on the native SDKs please refer to the App integration guides available on this portal.&lt;br /&gt;
&lt;br /&gt;
==  Implementation ==&lt;br /&gt;
This guide covers implementation covers&lt;br /&gt;
&lt;br /&gt;
* the implementation of React-Native bridges for iOS and Android&lt;br /&gt;
* the usage of the exposed Javascript API&lt;br /&gt;
&lt;br /&gt;
What we will not cover is the general setup of React-Native applications. If you are new to React-Native please refer to [https://facebook.github.io/react-native/ React-Native] for documentation.&lt;br /&gt;
&lt;br /&gt;
For simplicity we have focused on implementing a single instance of the Nielsen SDK. Should there be the need for multiple instances developers have to add some logic for that.&lt;br /&gt;
&lt;br /&gt;
== Setting up your Environment  ==&lt;br /&gt;
&amp;lt;div class=&amp;quot;section-container auto&amp;quot; data-section&amp;gt;&lt;br /&gt;
  &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;iOS&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first step is to ensure that the following frameworks and libraries are imported into the Frameworks folder of the iOS Xcode project before working with the Nielsen SDK.&lt;br /&gt;
&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
&lt;br /&gt;
Nielsens App SDK is compatible with Apple iOS versions 9.0 and above.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; &lt;br /&gt;
  &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;Android&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
The first step is to add the AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine to the libs folder (might have to be created) for the Android part of your project.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;android/app/libs&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next step is to add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Library'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Classes/package&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; &lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Creating React-Native bridges for the Nielsen SDK ==&lt;br /&gt;
In order to be able to use Nielsens native SDKs React-Native bridges have to be implemented and added to the iOS and Android projects. The following shows implementations for both platforms, that provide the basic methods to start measuring the app. The source code can be copied from below to provide an easy start.&lt;br /&gt;
&lt;br /&gt;
Please refer to the integration guides for Nielsens native SDKs to get a deeper understanding of the technical detail.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;section-container auto&amp;quot; data-section&amp;gt;&lt;br /&gt;
  &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;iOS&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The iOS implementation of the bridge module consists of two files, a header and an implementation file, written in Objective-c. These two files need to be added to the iOS XCode project.&lt;br /&gt;
&lt;br /&gt;
The header file is &amp;lt;code&amp;gt;NielsenReactBridge.h&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
// Copyright &amp;lt;2018&amp;gt; &amp;lt;The Nielsen Company&amp;gt;&lt;br /&gt;
// &lt;br /&gt;
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files&lt;br /&gt;
// (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,&lt;br /&gt;
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is&lt;br /&gt;
// furnished to do so, subject to the following conditions:&lt;br /&gt;
// &lt;br /&gt;
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
// &lt;br /&gt;
// THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES&lt;br /&gt;
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE&lt;br /&gt;
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR&lt;br /&gt;
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;br /&gt;
&lt;br /&gt;
#import &amp;lt;React/RCTBridgeModule.h&amp;gt;&lt;br /&gt;
#import &amp;lt;React/RCTEventEmitter.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@interface NielsenReactBridge : RCTEventEmitter &amp;lt;RCTBridgeModule&amp;gt;&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The actual implementation of the module happens in &amp;lt;code&amp;gt;NielsenReactBridge.m&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
// Copyright &amp;lt;2018&amp;gt; &amp;lt;The Nielsen Company&amp;gt;&lt;br /&gt;
// &lt;br /&gt;
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files&lt;br /&gt;
// (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,&lt;br /&gt;
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is&lt;br /&gt;
// furnished to do so, subject to the following conditions:&lt;br /&gt;
// &lt;br /&gt;
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
// &lt;br /&gt;
// THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES&lt;br /&gt;
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE&lt;br /&gt;
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR&lt;br /&gt;
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;br /&gt;
&lt;br /&gt;
#import &amp;quot;NielsenReactBridge.h&amp;quot;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
static NSString *const TAG = @&amp;quot;NielsenReactBridge&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
@interface NielsenReactBridge() &amp;lt;NielsenAppApiDelegate&amp;gt;&lt;br /&gt;
@property (strong) NielsenAppApi* nlsSDk;&lt;br /&gt;
@end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@implementation NielsenReactBridge&lt;br /&gt;
RCT_EXPORT_MODULE();&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Since we need to communicate the opt-out url to javascript via events&lt;br /&gt;
 * we need to implement the following method&lt;br /&gt;
 */&lt;br /&gt;
- (NSArray&amp;lt;NSString *&amp;gt; *)supportedEvents&lt;br /&gt;
{&lt;br /&gt;
  return @[@&amp;quot;OptOutUrl&amp;quot;];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * A logging helper method&lt;br /&gt;
 */&lt;br /&gt;
void NLSLog(NSString* tag, NSString* format, ...)&lt;br /&gt;
{&lt;br /&gt;
  va_list argList;&lt;br /&gt;
  va_start(argList, format);&lt;br /&gt;
  NSLog(@&amp;quot;%@&amp;quot;, [[NSString alloc] initWithFormat:[NSString stringWithFormat:@&amp;quot;[%@]: %@&amp;quot;, tag, format] arguments: argList]);&lt;br /&gt;
  va_end(argList);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Init creates the SDK instance and passes on the provided metadata.&lt;br /&gt;
 * appInfo is simply passed to initWithAppInfo since the SDK already &lt;br /&gt;
 * performs error checking&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(init:(NSDictionary *)appInfo)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;init called with metadat '%@''&amp;quot;, appInfo);&lt;br /&gt;
&lt;br /&gt;
  if (!self.nlsSDk) {&lt;br /&gt;
    self.nlsSDk= [[NielsenAppApi alloc] initWithAppInfo:appInfo delegate:self];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's play method. The provided metadata is &lt;br /&gt;
 * simply passed on&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(play:(NSDictionary *)channelInfo)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;play called with metadata '%@'&amp;quot;, channelInfo);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk play:channelInfo];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's loadMetadata method. The provided contentMetaData is &lt;br /&gt;
 * simply passed on&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(loadMetadata:(NSDictionary *)contentMetaData)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;loadMetadata called with '%@'&amp;quot;, contentMetaData);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk loadMetadata:contentMetaData];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's setPlayheadPosition method. The provided playhead is &lt;br /&gt;
 * simply passed on to the SDK&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(setPlayheadPosition:(nonnull NSNumber *)ph)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;setHeadPosition called with '%@'&amp;quot;,ph);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk playheadPosition:[ph longLongValue]];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's stop method. &lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(stop)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;stop called&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk stop];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Wrapper for the SDK's end method. &lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(end)&lt;br /&gt;
{&lt;br /&gt;
  NLSLog(TAG, @&amp;quot;end called&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  if (self.nlsSDk) {&lt;br /&gt;
    [self.nlsSDk end];&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * optOutUrl retrieves the url from the SDK instance and fires off the&lt;br /&gt;
 * OptOutUrl event, so the url can be captured&lt;br /&gt;
 */&lt;br /&gt;
RCT_EXPORT_METHOD(optOutUrl)&lt;br /&gt;
{&lt;br /&gt;
  [self sendEventWithName:@&amp;quot;OptOutUrl&amp;quot; body:@{@&amp;quot;url&amp;quot;: self.nlsSDk.optOutURL}];&lt;br /&gt;
}&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; &lt;br /&gt;
  &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;Android&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Android implementation of the bridge module consists of two files, an implementation of a NielsenPackage to announce the actual module and the implementation of NielsenReactBridge itself. The implementations have been put into the Java package&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com.nielsen.app.react&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The package implementation is in &amp;lt;code&amp;gt;com/nielsen/app/react/NielsenPackage.java&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// Copyright &amp;lt;2018&amp;gt; &amp;lt;The Nielsen Company&amp;gt;&lt;br /&gt;
// &lt;br /&gt;
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files&lt;br /&gt;
// (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,&lt;br /&gt;
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is&lt;br /&gt;
// furnished to do so, subject to the following conditions:&lt;br /&gt;
// &lt;br /&gt;
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
// &lt;br /&gt;
// THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES&lt;br /&gt;
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE&lt;br /&gt;
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR&lt;br /&gt;
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;br /&gt;
&lt;br /&gt;
package com.nielsen.app.react;&lt;br /&gt;
&lt;br /&gt;
import com.facebook.react.bridge.NativeModule;&lt;br /&gt;
import com.facebook.react.bridge.ReactApplicationContext;&lt;br /&gt;
import com.facebook.react.ReactPackage;&lt;br /&gt;
import com.facebook.react.uimanager.ViewManager;&lt;br /&gt;
import com.nielsen.app.react.NielsenReactBridge;&lt;br /&gt;
import java.util.ArrayList;&lt;br /&gt;
import java.util.Collections;&lt;br /&gt;
import java.util.List;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 */&lt;br /&gt;
public class NielsenPackage implements ReactPackage {&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Override createNativeModules to return our bridge module&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public List&amp;lt;NativeModule&amp;gt; createNativeModules(ReactApplicationContext reactContext) {&lt;br /&gt;
        List&amp;lt;NativeModule&amp;gt; modules = new ArrayList&amp;lt;&amp;gt;();&lt;br /&gt;
        modules.add(new NielsenReactBridge(reactContext));&lt;br /&gt;
&lt;br /&gt;
        return modules;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
    */&lt;br /&gt;
    @Override&lt;br /&gt;
    public List&amp;lt;ViewManager&amp;gt; createViewManagers(ReactApplicationContext reactContext) {&lt;br /&gt;
        return Collections.emptyList();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com/nielsen/app/react/NielsenReactBridge.java&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
// Copyright &amp;lt;2018&amp;gt; &amp;lt;The Nielsen Company&amp;gt;&lt;br /&gt;
// &lt;br /&gt;
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files&lt;br /&gt;
// (the &amp;quot;Software&amp;quot;), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,&lt;br /&gt;
// merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is&lt;br /&gt;
// furnished to do so, subject to the following conditions:&lt;br /&gt;
// &lt;br /&gt;
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&lt;br /&gt;
// &lt;br /&gt;
// THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES&lt;br /&gt;
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE&lt;br /&gt;
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR&lt;br /&gt;
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.&lt;br /&gt;
&lt;br /&gt;
package com.nielsen.app.react;&lt;br /&gt;
&lt;br /&gt;
import android.util.Log;&lt;br /&gt;
import com.facebook.react.bridge.LifecycleEventListener;&lt;br /&gt;
import com.facebook.react.bridge.ReactApplicationContext;&lt;br /&gt;
import com.facebook.react.bridge.ReactContextBaseJavaModule;&lt;br /&gt;
import com.facebook.react.modules.core.DeviceEventManagerModule;&lt;br /&gt;
import com.facebook.react.bridge.ReactMethod;&lt;br /&gt;
import com.facebook.react.bridge.ReadableMap;&lt;br /&gt;
import com.facebook.react.bridge.WritableMap;&lt;br /&gt;
import com.facebook.react.bridge.Arguments;&lt;br /&gt;
import com.facebook.react.bridge.ReadableMapKeySetIterator;&lt;br /&gt;
import com.nielsen.app.sdk.AppSdk;&lt;br /&gt;
import com.nielsen.app.sdk.IAppNotifier;&lt;br /&gt;
import com.nielsen.app.sdk.AppLaunchMeasurementManager;&lt;br /&gt;
import org.json.JSONObject;&lt;br /&gt;
import org.json.JSONException;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * NielsenReactBridge is the class briding between react JS code&lt;br /&gt;
 * and the native Nielsen SDK.&lt;br /&gt;
 */&lt;br /&gt;
public class NielsenReactBridge extends ReactContextBaseJavaModule &lt;br /&gt;
                                implements IAppNotifier, LifecycleEventListener {&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
    */&lt;br /&gt;
    private static final String NIELSEN_TAG = &amp;quot;NielsenReactBridge&amp;quot;;&lt;br /&gt;
    private AppSdk mAppSdk = null; // the AppSdk main object&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Constructor for the NielsenReactBridge&lt;br /&gt;
     * Adds the new instance as LifeCycleEventListener for conttex&lt;br /&gt;
     * @param context  The react application context&lt;br /&gt;
     */&lt;br /&gt;
    public NielsenReactBridge(ReactApplicationContext context) {&lt;br /&gt;
        super(context);&lt;br /&gt;
        context.addLifecycleEventListener(this);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements getName method from ReactContextBaseJavaModule&lt;br /&gt;
     * @return  The constant string 'NielsenReactBridge'&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public String getName() {&lt;br /&gt;
        return &amp;quot;NielsenReactBridge&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements getName method from IAppNotifier&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onAppSdkEvent(long l, int i, String s) {}&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Initializes the module for use &lt;br /&gt;
     * @param obj   An instance of ReadableMap (mapped JS object) containing&lt;br /&gt;
     *              initialization meta data&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void init(final ReadableMap obj) {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG, &amp;quot;Called init&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        if (null == mAppSdk) {&lt;br /&gt;
            try {&lt;br /&gt;
                JSONObject appSdkConfig = readableMapToJSONObject(obj);&lt;br /&gt;
                mAppSdk = new AppSdk(getReactApplicationContext(), appSdkConfig, this);&lt;br /&gt;
                if (!mAppSdk.isValid())&lt;br /&gt;
                {&lt;br /&gt;
                    Log.e(NIELSEN_TAG, &amp;quot;SDK Init failed&amp;quot;);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch(Exception ex) {&lt;br /&gt;
            }   &lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Static method to convert ReadableMap instances to JSONObject instances&lt;br /&gt;
     * (used by the Nielsen SDK)&lt;br /&gt;
     * @param obj   The ReadableMap instance to be converted&lt;br /&gt;
     * @return      An instance of JSONObject containing the mapped JS object&lt;br /&gt;
     *              values (if successful, empty otherwise) &lt;br /&gt;
     */&lt;br /&gt;
    static private JSONObject readableMapToJSONObject(final ReadableMap obj) {&lt;br /&gt;
&lt;br /&gt;
        JSONObject ret = new JSONObject();&lt;br /&gt;
&lt;br /&gt;
        try {&lt;br /&gt;
            ReadableMapKeySetIterator it = obj.keySetIterator();&lt;br /&gt;
            while (it.hasNextKey()) {&lt;br /&gt;
                String key = it.nextKey();&lt;br /&gt;
                ret.put(key, obj.getDynamic(key).asString());&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        catch (JSONException ex) {&lt;br /&gt;
            Log.e(NIELSEN_TAG, ex.getMessage());&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return ret;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK play method. Simply forwards calls &lt;br /&gt;
     * to the SDK.&lt;br /&gt;
     * @param obj   ReadableMap instance containing the mapped JS meta&lt;br /&gt;
     *              data object, e.g. {channelName: 'channel name here'}&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void play(final ReadableMap obj) {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG, &amp;quot;Called play &amp;quot; + obj.toString());&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            JSONObject playObject = readableMapToJSONObject(obj);&lt;br /&gt;
            mAppSdk.play(playObject);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK loadMetadata method. Simply forwards calls &lt;br /&gt;
     * to the SDK.&lt;br /&gt;
     * @param obj   ReadableMap instance containing the mapped JS meta&lt;br /&gt;
     *              data object&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void loadMetadata(final ReadableMap obj) {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called loadMetadata&amp;quot;);&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            JSONObject contentMetadata = readableMapToJSONObject(obj);&lt;br /&gt;
            mAppSdk.loadMetadata(contentMetadata);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK setPlayheadPosition method. Simply &lt;br /&gt;
     * forwards calls to the SDK.&lt;br /&gt;
     * @param ph    The current playhead position&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void setPlayheadPosition(final Double ph) {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called setPlayHeadPosition: &amp;quot; + &amp;quot; &amp;quot; + ph);&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            mAppSdk.setPlayheadPosition(ph.longValue());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK stop method. Simply &lt;br /&gt;
     * forwards calls to the SDK.&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void stop() {&lt;br /&gt;
        Log.d(NIELSEN_TAG, &amp;quot;Called stop&amp;quot;);&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            mAppSdk.stop();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper for the Nielsen SDK end method. Simply &lt;br /&gt;
     * forwards calls to the SDK.&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void end() {&lt;br /&gt;
        &lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called end&amp;quot;);&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            mAppSdk.end();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Wrapper to retrieve the optOutUrl from the Nielsen SDK. &lt;br /&gt;
     * Emits a &amp;quot;OptOutUrl&amp;quot; event with the url as payload.&lt;br /&gt;
     * Needs to be catched in JS&lt;br /&gt;
     */&lt;br /&gt;
    @ReactMethod&lt;br /&gt;
    public void optOutUrl() {&lt;br /&gt;
&lt;br /&gt;
        WritableMap params = Arguments.createMap();&lt;br /&gt;
        if (null != mAppSdk) {&lt;br /&gt;
            params.putString(&amp;quot;url&amp;quot;, mAppSdk.userOptOutURLString());&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        getReactApplicationContext()&lt;br /&gt;
        .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)&lt;br /&gt;
        .emit(&amp;quot;OptOutUrl&amp;quot;, params);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements LifecycleEventListener's onHostResume method.&lt;br /&gt;
     * Uses AppLaunchMeasurementManager.appInForeground to notify SDK about&lt;br /&gt;
     * app coming to foreground again&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onHostResume() {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called onHostResume&amp;quot;);&lt;br /&gt;
        AppLaunchMeasurementManager.appInForeground(getReactApplicationContext());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements LifecycleEventListener's onHostPause method.&lt;br /&gt;
     * Uses AppLaunchMeasurementManager.appInBackground to notify SDK about&lt;br /&gt;
     * app going to background&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onHostPause() {&lt;br /&gt;
&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called onHostPause&amp;quot;);&lt;br /&gt;
        AppLaunchMeasurementManager.appInBackground(getReactApplicationContext());&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /**&lt;br /&gt;
     * Implements LifecycleEventListener's onHostDestroy method.&lt;br /&gt;
     */&lt;br /&gt;
    @Override&lt;br /&gt;
    public void onHostDestroy() {&lt;br /&gt;
        Log.d(NIELSEN_TAG,&amp;quot;Called onHostDestroy&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The package needs to be provided in the getPackages method of the MainApplication.java file. This file exists under the android folder in your react-native application directory. The path to this file is: android/app/src/main/java/com/your-app-name/MainApplication.java.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
import com.nielsen.app.react.NielsenPackage;   //&amp;lt;-- Import the package in MainApplication.java&lt;br /&gt;
//...&lt;br /&gt;
&lt;br /&gt;
    protected List&amp;lt;ReactPackage&amp;gt; getPackages() {&lt;br /&gt;
        return Arrays.&amp;lt;ReactPackage&amp;gt;asList(&lt;br /&gt;
                //...,&lt;br /&gt;
                new NielsenPackage()); // &amp;lt;-- Add the bridge package to the getPackages method.&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In order to import the bridges into the Javascript context, create a file&lt;br /&gt;
&amp;lt;code&amp;gt;NielsenModule.js&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
import { NativeModules } from 'react-native'&lt;br /&gt;
&lt;br /&gt;
export default NativeModules.NielsenReactBridge&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== SDK Initialization ==&lt;br /&gt;
The bridge implementations above allow the usage of one instance of the Nielsen App SDK. The latest version of the Nielsen App SDK allows instantiating multiple instances of the SDK object, which can be used simultaneously without any issue. For more information on this please read the relevant App SDK Guide.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.&lt;br /&gt;
&lt;br /&gt;
* The appid is provided by the Nielsen Technical Account Manager (TAM). The appid is a GUID data type and is specific to the application.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter / Argument !! Description !! Source !! Required? !! Example&lt;br /&gt;
|-&lt;br /&gt;
| appid || Unique id for the application assigned by Nielsen. It is GUID data type.|| Nielsen-specified || Yes || PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&lt;br /&gt;
|-&lt;br /&gt;
| appname || Name of the application || Client-defined || No|| Nielsen Sample App&lt;br /&gt;
|-&lt;br /&gt;
| appversion || Current version of the app used || Client-defined || No || &amp;quot;1.0.2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Nielsen collection facility to which the SDK should connect.&lt;br /&gt;
'''Italian Clients'''&lt;br /&gt;
* &amp;quot;it&amp;quot;&lt;br /&gt;
|| Nielsen-specified || Yes || &amp;quot;it&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || Enables Nielsen console logging. Only required for testing&lt;br /&gt;
|| Nielsen-specified || Optional || &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Sample SDK Initialization Code ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
    import NielsenModule from './NielsenModule';&lt;br /&gt;
&lt;br /&gt;
    let appInformation = {&amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
                          &amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
                          &amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
                          &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
                          &amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot;};&lt;br /&gt;
   NielsenModule.init(appInformation);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== APP SDK Error &amp;amp; Event Codes ==&lt;br /&gt;
To view the Error and Event codes for iOS and Android, please review the [[APP SDK Event Codes|App SDK Event Code]] Reference page.&lt;br /&gt;
&lt;br /&gt;
== Configure Payload ==&lt;br /&gt;
All metadata is passed to the bridges in form of objects containing the in the following described properties. An example metadata object could look like&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
let metadata = {&lt;br /&gt;
    'type':'content',&lt;br /&gt;
    'assetid':'asset12345',&lt;br /&gt;
    'program':'My Program',&lt;br /&gt;
    'title':'My Title',&lt;br /&gt;
    'length':'42',&lt;br /&gt;
    'airdate':'20180302 16:32:00',&lt;br /&gt;
    'isfullepisode':'n',&lt;br /&gt;
    'adloadtype':'2'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; &lt;br /&gt;
&lt;br /&gt;
The following section will explain the different values.&lt;br /&gt;
&lt;br /&gt;
=== Configure metadata === &lt;br /&gt;
Configure metadata should remain constant throughout the completion of an episode or live stream.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| channelName	|| Any string representing the channel/stream	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Content metadata ===&lt;br /&gt;
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset || custom &amp;lt;br&amp;gt;(no [[Special Characters]]) || Yes&lt;br /&gt;
|-&lt;br /&gt;
| program ||name of program (25 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| title ||name of program (40 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || Yes&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear TV; if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || YYYYMMDD HH24:MI:SS || Yes&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || Yes&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches TV ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || Yes&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
The ad metadata (if applicable) should be passed for each individual ad, if ads are available during or before the stream begins.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Static Measurement ===&lt;br /&gt;
The Nielsen SDK is able to monitor Application launch events and how long your app has been running. Once the Nielsen module has been Initialized, pass a metadata object to loadMeta data that follows these rules: &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Data Type !! Value !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type || asset type || fixed || &amp;lt;code&amp;gt;'static'&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID for each article || dynamic || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| 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&lt;br /&gt;
|}&lt;br /&gt;
You only need to do this once upon app start.&lt;br /&gt;
&lt;br /&gt;
== Configure API Calls ==&lt;br /&gt;
=== Sample API Sequence ===&lt;br /&gt;
A Sample API sequence could follow this flow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
|On App Start||&amp;lt;code&amp;gt;NielsenModule.loadMetadata(contentMetadata);&amp;lt;/code&amp;gt; || // contentMetadata Object contains the JSON metadata for the impression&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;NielsenModule.play(channelName);&amp;lt;/code&amp;gt; || // channelName contains JSON metadata of channel/video name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;NielsenModule.loadMetadata(contentMetadataObject);&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;NielsenModule.playheadPosition(position);&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;NielsenModule.end();&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
=== Life cycle of SDK instance ===&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[DCR_Video_APP_SDK#play|play]] and [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[DCR_Video_APP_SDK#stop|stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[DCR_Video_APP_SDK#end|end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] and  [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence of Calls ===&lt;br /&gt;
=== play ===&lt;br /&gt;
Use the play function to pass the channel descriptor information through channelName parameter when the user taps the '''Play''' button on the player.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.play(channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
The loadMetadata function is used to inform the SDK about new content. The contentMetadata object passed in should contain the values as described above.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.loadMetadata(contentMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== playheadPosition ===&lt;br /&gt;
Use playheadPosition to tell the SDK about the current position in the video. For live content this should be the UTC timestamp in seconds, for on-demand content simply the second in the video.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.playheadPosition(playheadPos);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== stop ===&lt;br /&gt;
Tell the SDK that content playback has stopped.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.stop();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== end ===&lt;br /&gt;
When content stop is initiated and content cannot be resumed from the same position (it can only be restarted from the beginning of stream).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;   NielsenModule.end();&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Privacy and Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
=== Opt-Out Implementation ===&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL for the Nielsen Privacy web page should be retrieved from via the &amp;lt;code&amp;gt;optOutURL()&amp;lt;/code&amp;gt; method of the SDK bridge and opened in 'WebView' / External browser.&lt;br /&gt;
*If the returned value is null or empty, handle the exception gracefully and retry later.&lt;br /&gt;
&lt;br /&gt;
Due to the limitation that native methods can't return values directly, the URL will be sent to the Javascript context as &amp;quot;OptOutUrl&amp;quot; event, with the url as the payload.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
    const nielsen = new NativeEventEmitter(NielsenModule);&lt;br /&gt;
    &lt;br /&gt;
    const subscription = nielsen.addListener(&lt;br /&gt;
      'OptOutUrl',&lt;br /&gt;
      (data) =&amp;gt; { &lt;br /&gt;
         //display data.url&lt;br /&gt;
      }&lt;br /&gt;
    );&lt;br /&gt;
    NielsenModule.optOutUrl();&lt;br /&gt;
   //...&lt;br /&gt;
   subscription.remove(); // do not forget to unsubscribe&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make one update to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_devDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Example:&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
    let appInformation = {&lt;br /&gt;
            &amp;quot;appid&amp;quot;: &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
    };&lt;br /&gt;
    NielsenModule.init(appInformation);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=International&amp;diff=2650</id>
		<title>International</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=International&amp;diff=2650"/>
		<updated>2018-04-16T12:41:50Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: remove &amp;quot;german&amp;quot; block (because of legal reasons for now) - can be redone by history&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
{{CategoryIcon|International.png|International}}&lt;br /&gt;
&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Please contact your Nielsen representative for documentation if the guides for your country aren't listed.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; | Downloads&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width: 90px;&amp;quot; |{{SmallIcon|DownloadIcon.png|alt=Cloud API}} &lt;br /&gt;
|style=&amp;quot;width: 90px;&amp;quot; | {{SmallIcon|SDKIcon.png}}&lt;br /&gt;
| '''[[Digital Downloads|SDK Downloads]]'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; | Italy&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; |&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | &lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | OS&lt;br /&gt;
!| Guide&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;7&amp;quot; | {{SmallIcon|ITFlagIcon.png}}&lt;br /&gt;
| rowspan=&amp;quot;7&amp;quot; | {{SmallIcon|SDKIcon.png}}&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | {{OSIcon|VideoIcon.png}}&lt;br /&gt;
| {{OSIcon|macOSIcon.png}}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{OSIcon|AndroidIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Video App SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | {{OSIcon|BrowserIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Video Browser SDK (6.0.0)]]'''&lt;br /&gt;
|-&lt;br /&gt;
| '''[[DCR Italy Video Browser SDK (6.0.1)]] Object Video only'''&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;5&amp;quot; | {{OSIcon|StaticIcon.png}}&lt;br /&gt;
| {{OSIcon|macOSIcon.png}}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{OSIcon|AndroidIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Static App SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
| {{OSIcon|BrowserIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Static Browser SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
|  {{OSIcon|FacebookIcon.png|alt=Facebook Instant Articles}}&lt;br /&gt;
| '''[[DCR Italy Static Facebook Instant Articles Browser SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
|  {{OSIcon|AMPIcon.png|alt=Google AMP}}&lt;br /&gt;
| '''[[DCR Italy Static Google AMP Cloud API]]'''&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=2572</id>
		<title>DCR Italy Video Browser SDK (6.0.1)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=2572"/>
		<updated>2018-03-13T09:29:34Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show how to integrate the Nielsen Software Development Kit (SDK) to enable Digital Content Ratings (DCR) video measurement on browser players.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID, clientid and vcid is needed. These values are provided by Nielsen.&lt;br /&gt;
&lt;br /&gt;
The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
AppID: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The clientid is your 'parent# or companyid'&lt;br /&gt;
clientid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;XX-XXXXXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The vcid is your channel id&lt;br /&gt;
vcid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&amp;quot;xXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
* Add Static Queue Snippet&lt;br /&gt;
* Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
=== Create SDK Instance ===&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
       clientid: &amp;quot;XX-XXXXXX&amp;quot;,  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
       vcid: &amp;quot;cXX&amp;quot;,            // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
       nol_sdkDebug: &amp;quot;debug&amp;quot;   // should be deleted when going live&lt;br /&gt;
    }&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following five values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site || &amp;lt;code&amp;gt;&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || &amp;lt;code&amp;gt;&amp;quot;any string value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value has to be passed in 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value has to be passed 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Nielsen console logging. Only required for testing. in 3rd parameter object || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK601.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;, nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
* content: identify video&lt;br /&gt;
* ad: identify each ad ('''for Italy there is no need to tag ads''')&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*video – &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to content (max. 40 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || &amp;lt;code&amp;gt;YYYYMMDD hh:mm:ss&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; - full episode&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt; - non-full episode&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load &amp;quot;1&amp;quot;&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI) &amp;quot;2&amp;quot;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| ✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| subbrand || subbrand/VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || Nielsen provided || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Content Object'''&lt;br /&gt;
... with all mandatory parameters - you may ignore the optional ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           &amp;quot;content&amp;quot;,&lt;br /&gt;
  assetid:        &amp;quot;VID123-123456&amp;quot;,&lt;br /&gt;
  program:        &amp;quot;program name&amp;quot;,&lt;br /&gt;
  title:          &amp;quot;episode title&amp;quot;,&lt;br /&gt;
  length:         &amp;quot;1020&amp;quot;,&lt;br /&gt;
  airdate:        &amp;quot;19700101 00:00:00&amp;quot;,&lt;br /&gt;
  isfullepisode:  &amp;quot;y&amp;quot;,&lt;br /&gt;
  adloadtype:     &amp;quot;2&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
=== Ad Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Audiweb there is no need to tag ads in video stream ... you may ignore this paragraph. If there are ads in your stream, but not tagged than simply do nothing while ad is playing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of ad || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || uniqueID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Ad Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;//create ad object&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: &amp;quot;AD-1&amp;quot;,&lt;br /&gt;
  type:    &amp;quot;preroll&amp;quot;&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''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.&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is &amp;lt;code&amp;gt;ggPM()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM('event', parameter, ...);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Number !! Values to pass !! Event Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'3'&amp;lt;/code&amp;gt; || content/ad metadata object || load content metadata || Load metadata event for content. Has to be called at the very first beginning of each stream.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'5'&amp;lt;/code&amp;gt; || playhead position || content play || Call when content or ads start playing or resumes from pause. &lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'6'&amp;lt;/code&amp;gt; || playhead position || pause || Call when content or ads is pausing. Use Event 5 to resume ...&lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt; || playhead position || stop || Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'8'&amp;lt;/code&amp;gt; || playhead position from, playhead position to || seek || Call when scrubbing forward or backward with playhead position 'from' and 'to'&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt; || content/ad metadata object || load ad metadata || Call at the beginning of each ad, don’t use ‘play’ (event 5) if event 15 is used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; || playhead position || playhead position || '''VOD''': current position in seconds. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
Note: has to be called on a secondly basis.&lt;br /&gt;
For each ad the playheads starts with 0 (no Live unix timestamp for ads)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt; || playhead position || end || This event has to be called '''once''' for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Event Lifecycle ===&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;example '''without''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': if there are ads played in stream simply use a pause (event 6) when ads start playing and a play (event 5) when content start playing.&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&amp;lt;big&amp;gt; example '''with''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// Preroll&lt;br /&gt;
nSdkInstance.ggPM('15', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Midroll&lt;br /&gt;
nSdkInstance.ggPM('15', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// Postroll&lt;br /&gt;
nSdkInstance.ggPM('15', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Italy there is no need to tag ads in video stream ... ignore &amp;quot;with ads&amp;quot; example!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': Event &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling event &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when buffering occurs you have to send a event 6 (pause) and after buffering finished a 5 (play).&lt;br /&gt;
&lt;br /&gt;
'''Note''': For Ad Pods, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note''': When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Pause'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; is used for handling pause. To indicate pause, stop passing the playhead position to the SDK and send Event 6 with playhead once. When content resumes, begin sending the playhead again with the correct playhead value. Also if buffering occurs for more than 1 second you may use Event 6 (pause) to indicate that.&lt;br /&gt;
e.g. pause at 1m2s and resume after a couple of seconds:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // now send nothing to SDK until player resumes (automatically because of buffering ends or user unpauses/resumes play&lt;br /&gt;
nSdkInstance.ggPM('5', 62); // ONLY WHEN PLAYING CONTENT (not ads!) - play/5 when resume occurs (when user click play or buffering ends)&lt;br /&gt;
nSdkInstance.ggPM('49', 63);&lt;br /&gt;
nSdkInstance.ggPM('49', 64);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Seek'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; is used for handling forward/backward seek. To indicate seek, send Event 8 with 'from' and 'to' playhead.&lt;br /&gt;
e.g. seek from 1m2s to 2m0s:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // use pause, because buffering will occur (to be on safe side)&lt;br /&gt;
nSdkInstance.ggPM('8', 62,120);&lt;br /&gt;
nSdkInstance.ggPM('5', 120); // ONLY WHEN PLAYING CONTENT (not ads!) - play/5 when resuming&lt;br /&gt;
nSdkInstance.ggPM('49', 120);&lt;br /&gt;
nSdkInstance.ggPM('49', 121);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Interruption Scenarios===&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var stopped = false;&lt;br /&gt;
function closePlayer() {&lt;br /&gt;
	if (stopped) {return;}&lt;br /&gt;
	stopped = true;&lt;br /&gt;
	if (inMidroll) {    // Only inside a midroll indicate &amp;lt;stop&amp;gt; for the ad&lt;br /&gt;
		nSdkInstance.ggPM(7, playheadPositionMidroll);&lt;br /&gt;
	}&lt;br /&gt;
	nSdkInstance.ggPM(57, playheadPositionContent);    // Indicate &amp;lt;end&amp;gt; for the content&lt;br /&gt;
	nSdkInstance.ggPM(7, playheadPositionContent);    // Indicate &amp;lt;stop&amp;gt; for the content&lt;br /&gt;
};&lt;br /&gt;
window.addEventListener(&amp;quot;beforeunload&amp;quot;, function (e) {&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
window.addEventListener(&amp;quot;pagehide&amp;quot;, function (e) {	// for iOS mobile &amp;quot;pagehide&amp;quot; recommended by apple&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2571</id>
		<title>DCR Italy Video Browser SDK (6.0.0)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2571"/>
		<updated>2018-03-13T09:26:37Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID is needed. The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration from Nielsen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  apid: &amp;quot;XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot; // eg. PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
*Add Static Queue Snippet&lt;br /&gt;
*Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
===Create SDK Instance===&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization API call:&lt;br /&gt;
&lt;br /&gt;
==== Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,{nol_sdkDebug: &amp;quot;debug&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following  values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter	!! Description	!! Required !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid	&lt;br /&gt;
|| Unique ID assigned to player/site. &lt;br /&gt;
*Test: begins with ‘T’ and is used for testing &lt;br /&gt;
*Production: begins with ‘P’ and is used in live environment when testing and certification is completed&lt;br /&gt;
||Yes||'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&lt;br /&gt;
|-&lt;br /&gt;
|instanceName ||	Name of SDK instance ||Yes	 ||	&amp;quot;any string value&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug	|| Enables Nielsen console logging. Only required for testing	||Optional	|| nol_sdkDebug: &amp;quot;debug&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;apid&amp;gt;.js, will be downloaded based on the apid and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK600.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
==== Example SDK Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
*content: identify video&lt;br /&gt;
*ad: identify each ad&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type ||	Type of asset	|| &amp;quot;content&amp;quot;	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid	|| Unique ID assigned to content (max. 40 characters) || custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| program	|| Name of program (25 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| title	|| Episode title (40 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| length	|| Length of content in seconds for VOD (Video on demand). The value for live stream content is 86400 ||&lt;br /&gt;
*&amp;quot;seconds&amp;quot;– VOD&lt;br /&gt;
*&amp;quot;86400&amp;quot;– Live Stream&lt;br /&gt;
||	&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate	|| The airdate in the linear TV. Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; ||	YYYYMMDD hh:mm:ss	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode	|| Full episode flag ||	&lt;br /&gt;
*&amp;quot;y&amp;quot;– full episode&lt;br /&gt;
*&amp;quot;n&amp;quot;– non full episode	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
|adloadtype	|| type of ad load:&lt;br /&gt;
* 1) Linear – matches TV ad load &lt;br /&gt;
* 2) Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;1&amp;quot; – content with linear ads &lt;br /&gt;
*&amp;quot;2&amp;quot; – content with dynamic ads	&lt;br /&gt;
||&lt;br /&gt;
✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Example Content Object =====&lt;br /&gt;
&lt;br /&gt;
'''Note:''' all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           'content',&lt;br /&gt;
  assetid:        'VID123-123456',&lt;br /&gt;
  program:        'program name',&lt;br /&gt;
  title:          'episode title',&lt;br /&gt;
  length:         '1020',    // length in seconds (String)&lt;br /&gt;
  airdate:        '19700101 00:00:00',&lt;br /&gt;
  isfullepisode:  'y',&lt;br /&gt;
  adloadtype:     '2'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad, if ads are available during or before the stream (content) begins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example Ad Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create pre-roll ad object&lt;br /&gt;
var prerollMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: 'AD-1',&lt;br /&gt;
  type:    'preroll'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is ggPM().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
nSdkInstance.ggPM('event', parameter);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event name !! Values to pass !!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 'loadMetadata'	|| content/ad metadata object	|| Needs to be called at the beginning of each content/ad metadata object&lt;br /&gt;
|-&lt;br /&gt;
| 'setPlayheadPosition'&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;VOD (or ad ): || current position in seconds (integer) &amp;lt;br/&amp;gt;&lt;br /&gt;
*&amp;quot;Live: current UTC timestamp (seconds since January 1st 1970)&amp;lt;br/&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
Pass playhead position every second during playback&lt;br /&gt;
|-&lt;br /&gt;
| 'stop' ||	playhead position in seconds	|| Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| 'end'	|| playhead position in seconds	|| This event has to be called once for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Playhead position as integer&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' has to be called every second&lt;br /&gt;
&lt;br /&gt;
==== Example Events ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass ( Object ):''' Content Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', contentMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass  ( Object ):''' Pre-roll AD Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', prerollMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' setPlayheadPosition  |  '''Value Pass ( Integer ):''' playheadPosition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' stop  |  '''Value Pass ( Integer ):''' stopPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('stop', stopPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' end  |  '''Value Pass ( Integer ):''' endPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('end', endPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Interrupt Scenarios ==&lt;br /&gt;
&lt;br /&gt;
=== Pause Event ===&lt;br /&gt;
The setPlayheadPostion event is used for handling pause. To indicate pause, stop passing the playhead position to the SDK. Once the content resumes, begin sending the playhead again with the correct playhead value.&lt;br /&gt;
&lt;br /&gt;
=== Other Interrupt Scenarios ===&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var stopped = false;&lt;br /&gt;
function closePlayer() {&lt;br /&gt;
	if (stopped) {return;}&lt;br /&gt;
	stopped = true;&lt;br /&gt;
	if (inMidroll) {    // Only inside a midroll indicate &amp;lt;stop&amp;gt; for the ad&lt;br /&gt;
		nSdkInstance.ggPM('stop', playheadPositionMidroll);&lt;br /&gt;
	}&lt;br /&gt;
	nSdkInstance.ggPM('end', playheadPositionContent);    // Indicate &amp;lt;end&amp;gt; for the content&lt;br /&gt;
};&lt;br /&gt;
window.addEventListener(&amp;quot;beforeunload&amp;quot;, function (e) {&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
window.addEventListener(&amp;quot;pagehide&amp;quot;, function (e) {	// for iOS mobile &amp;quot;pagehide&amp;quot; recommended by apple&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==  SDK Event Lifecycle ==&lt;br /&gt;
&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
'''Note''' &lt;br /&gt;
*For Audiweb there is no need to tag ads in video stream ... please see 1st example how to use without ads!&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle without ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:even browser no ads.png]]&lt;br /&gt;
&lt;br /&gt;
==== Example without ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);  // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle with ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:event browser.png|event browser.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example with ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// PREROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end pre-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);&lt;br /&gt;
&lt;br /&gt;
// MIDROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
  &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end mid-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); &lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// POSTROLL&lt;br /&gt;
nSdkInstance.ggPM('loadmetadata', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); // end post-roll stream&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling 'stop', 'end', or 'loadmetadata'.&lt;br /&gt;
&lt;br /&gt;
'''Note :''' For Ad, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' For pre-roll ads you have to call the loadMetadata event for content at the start of stream and after the preroll&lt;br /&gt;
&lt;br /&gt;
== Nielsen Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
====Opt Back In====&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'debug'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
&lt;br /&gt;
====Example Production Initialization Call ====&lt;br /&gt;
Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;, &amp;quot;myPlayerName&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2468</id>
		<title>DCR Italy Video App SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2468"/>
		<updated>2018-02-15T15:45:11Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK:''' The Nielsen SDK package contains a variety of sample players for your reference.&lt;br /&gt;
If you do not have any of these prerequisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] guide for information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
==  Implementation ==&lt;br /&gt;
This guide covers implementation steps for iOS using Xcode and Android using Android Studio.&lt;br /&gt;
&lt;br /&gt;
== Setting up your  Development Environment  ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
xCode|&lt;br /&gt;
&amp;lt;big&amp;gt;&lt;br /&gt;
'''Configuring Xcode Development Environment''' &lt;br /&gt;
&amp;lt;/big&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 9.0 and above.&lt;br /&gt;
&lt;br /&gt;
The SDK uses the NSURLSession instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': All communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Importing Frameworks'''&amp;lt;/big&amp;gt;&lt;br /&gt;
The first step is to ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Swift'''&amp;lt;/big&amp;gt;&lt;br /&gt;
To import a set of Objective-C files in the same app target as your Swift code, you rely on an Objective-C bridging header to expose those files to Swift. Xcode offers to create this header file when you add a Swift file to an existing Objective-C app, or an Objective-C file to an existing Swift app.&lt;br /&gt;
&lt;br /&gt;
Select File/New File/Objective-C File  &amp;lt;br /&amp;gt;&lt;br /&gt;
Xcode will prompt you to create a bridging header.&lt;br /&gt;
[[File:bridgingheader 2x.png|600px|center|link=]] &amp;lt;br /&amp;gt;&lt;br /&gt;
Once this file has been created, you need to add the following:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Objective-C'''&amp;lt;/big&amp;gt;&lt;br /&gt;
Add the code &lt;br /&gt;
&amp;lt;syntaxhighlight lang =&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 to the View Controller’s header file.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
|Android =&lt;br /&gt;
&amp;lt;big&amp;gt;'''Configuring Android Development Environment'''&amp;lt;/big&amp;gt;'&lt;br /&gt;
*The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package.&lt;br /&gt;
&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Library'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Classes/package&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== SDK Initialization ==&lt;br /&gt;
The latest version of the Nielsen App SDK allows instantiating multiple instances of the SDK object, which can be used simultaneously without any issue. The sharedInstance API that creates a singleton object was deprecated prior to version 5.1.1. (Version 4.0 for Android)&lt;br /&gt;
&lt;br /&gt;
* A maximum of four SDK instances per appid are supported. When a fifth SDK instance is launched, the SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
* When four SDK instances exist, you must destroy an old instance before creating a new one.&lt;br /&gt;
&lt;br /&gt;
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.&lt;br /&gt;
&lt;br /&gt;
* The appid is provided by the Nielsen Technical Account Manager (TAM). The appid is a GUID data type and is specific to the application.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter / Argument !! Description !! Source !! Required? !! Example&lt;br /&gt;
|-&lt;br /&gt;
| appid || Unique id for the application assigned by Nielsen. It is GUID data type.|| Nielsen-specified || Yes || PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&lt;br /&gt;
|-&lt;br /&gt;
| appname || Name of the application || Client-defined || No|| Nielsen Sample App&lt;br /&gt;
|-&lt;br /&gt;
| appversion || Current version of the app used || Client-defined || No || &amp;quot;1.0.2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Nielsen collection facility to which the SDK should connect.&lt;br /&gt;
'''Italian Clients'''&lt;br /&gt;
* &amp;quot;it&amp;quot;&lt;br /&gt;
|| Nielsen-specified || Yes || &amp;quot;it&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || Enables Nielsen console logging. Only required for testing&lt;br /&gt;
|| Nielsen-specified || Optional || &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==== Sample SDK Initialization Code ====&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift  = &lt;br /&gt;
Swift 4.0 Example:&lt;br /&gt;
&amp;lt;code&amp;gt;NielsenInit.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
           &amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
            &amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
            &amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
            &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sample code using AVPlayer.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ViewController.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class ViewController: UIViewController, NielsenAppApiDelegate, AVPictureInPictureControllerDelegate, CLLocationManagerDelegate  {&lt;br /&gt;
    &lt;br /&gt;
    let avPlayerViewController = AVPlayerViewController()&lt;br /&gt;
    var avPlayer:AVPlayer?&lt;br /&gt;
    var nielsenAppApi: NielsenAppApi!&lt;br /&gt;
&lt;br /&gt;
  override func viewDidLoad() {&lt;br /&gt;
        super.viewDidLoad()&lt;br /&gt;
&lt;br /&gt;
self.nielsenAppApi = NielsenInit.createNielsenAppApi(delegate: self)&lt;br /&gt;
NSLog(&amp;quot;Nielsen SDK initialized&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Objective C = &lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;    &lt;br /&gt;
#import &amp;quot;NlsAppApiFactory.h&amp;quot;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@implementation NlsAppApiFactory&lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
{&lt;br /&gt;
    NSDictionary *appInformation = @{&lt;br /&gt;
                                     @&amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot;&lt;br /&gt;
                                     };&lt;br /&gt;
    return [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&lt;br /&gt;
}&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following would be the &amp;lt;code&amp;gt;NlsAppApiFactory.h&amp;lt;/code&amp;gt; file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@class NielsenAppApi;&lt;br /&gt;
@protocol NielsenAppApiDeligate;&lt;br /&gt;
&lt;br /&gt;
@interface NlsAppApiFactory : NSObject &lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppAPI *) createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appversion&amp;quot;, &amp;quot;1.0&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;DEBUG&amp;quot;); // only for debug builds&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&amp;lt;br /&amp;gt;&lt;br /&gt;
* Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== APP SDK Error &amp;amp; Event Codes ==&lt;br /&gt;
To view the Error and Event codes for iOS and Android, please review the [[APP SDK Event Codes|App SDK Event Code]] Reference page.&lt;br /&gt;
== Configure Payload ==&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift = &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
       let channelInfo = [&lt;br /&gt;
            &amp;quot;channelName&amp;quot;: &amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
        &lt;br /&gt;
        let contentMetadata = [&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
                &amp;quot;assetid&amp;quot;: &amp;quot;88675545&amp;quot;,&lt;br /&gt;
                &amp;quot;title&amp;quot;: &amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
                &amp;quot;isfullepisode&amp;quot;:&amp;quot;n&amp;quot;,&lt;br /&gt;
                &amp;quot;adloadtype&amp;quot;:&amp;quot;2&amp;quot;,&lt;br /&gt;
                &amp;quot;program&amp;quot;:&amp;quot;Program Name&amp;quot;,&lt;br /&gt;
                &amp;quot;length&amp;quot;:&amp;quot;3600&amp;quot;, &lt;br /&gt;
                &amp;quot;airdate&amp;quot;:&amp;quot;20171020 10:05:00&amp;quot;&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;     &lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt; &lt;br /&gt;
NSDictionary  *channelInfo = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;channelName&amp;quot;:@&amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
NSDictionary *contentMetadata = @&lt;br /&gt;
  {@&amp;quot;type&amp;quot;: @&amp;quot;content&amp;quot;,&lt;br /&gt;
  @&amp;quot;assetid&amp;quot;: [NSString stringWithFormat:@&amp;quot;ProgramAssetId-%d&amp;quot;, i],&lt;br /&gt;
  @&amp;quot;length&amp;quot;: @&amp;quot;3600&amp;quot;,&lt;br /&gt;
  @&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;title&amp;quot;: @&amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
  @&amp;quot;isfullepisode&amp;quot;: @&amp;quot;y&amp;quot;,&lt;br /&gt;
  @&amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
  @&amp;quot;airdate&amp;quot;: &amp;quot;20161013 20:00:00&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject channelInfo = new JSONObject()&lt;br /&gt;
    .put(&amp;quot;channelname&amp;quot;,&amp;quot;My Channel Name 1&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
JSONObject contentMetadata = new JSONObject()&lt;br /&gt;
//SDK Metadata&lt;br /&gt;
    .put(&amp;quot;type&amp;quot;, &amp;quot;content&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;assetid&amp;quot;, &amp;quot;vid345-67483&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;title&amp;quot;, &amp;quot;Program S3, EP1&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;length&amp;quot;, &amp;quot;3600&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;isfullepisode&amp;quot;, &amp;quot;y&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;adloadtype&amp;quot;, &amp;quot;2&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;airdate&amp;quot;, &amp;quot;20161013 20:00:00&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;   &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Configure metadata === &lt;br /&gt;
Configure metadata should remain constant throughout the completion of an episode or live stream.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| channelName	|| Any string representing the channel/stream	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Content metadata ===&lt;br /&gt;
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| program ||name of program (25 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| title ||name of program (40 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || Yes&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || Yes&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches TV ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || Yes&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
The ad metadata (if applicable) should be passed for each individual ad, if ads are available during or before the stream begins.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Configure API Calls ==&lt;br /&gt;
=== Sample API Sequence ===&lt;br /&gt;
A Sample API sequence could follow this flow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
|On App Start||&amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadata];&amp;lt;/code&amp;gt; || // contentMetadata Object contains the JSON metadata for the impression&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;[nielsenMeter play: channelName];&amp;lt;/code&amp;gt; || // channelName contains JSON metadata of channel/video name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadataObject];&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;[nielsenMeter end];&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
=== Life cycle of SDK instance ===&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[DCR_Video_APP_SDK#play|play]] and [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[DCR_Video_APP_SDK#stop|stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[DCR_Video_APP_SDK#end|end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## &amp;lt;code&amp;gt;appDisableApi&amp;lt;/code&amp;gt; is called&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (assign) BOOL appDisableApi;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] and  [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence of Calls ===&lt;br /&gt;
=== play ===&lt;br /&gt;
Use [[DCR_Video_APP_SDK#play|play]] to pass the channel descriptor information through channelName parameter when the user taps the '''Play''' button on the player.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;   [nielsenAppApi play:(JSONObject channelInfo)];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;    public void play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;nielsenAppApi?.play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void)loadMetadata:(id)contentMetadata;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void loadMetadata(JSONObject contentMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.loadMetadata(contentMetadata)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== playheadPosition ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void) playheadPosition: (long long) playheadPos&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Sending playheadposition for content ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
AVPlayer *player;&lt;br /&gt;
CMTime curTime=[player currentTime];&lt;br /&gt;
int pos = CMTimeGetSeconds(curTime);&lt;br /&gt;
[nAppApiObject playheadPosition:pos];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
        //Monitor the Playhead position of the AVPlayer&lt;br /&gt;
        let timeInterval: CMTime = CMTimeMakeWithSeconds(1.0,10)&lt;br /&gt;
        self.avPlayerViewController.player?.addPeriodicTimeObserver(forInterval: timeInterval, queue: DispatchQueue.main) {(elapsedTime: CMTime) -&amp;gt; Void in&lt;br /&gt;
            if self.avPlayerViewController.player!.currentItem?.status == .readyToPlay {&lt;br /&gt;
                let time : Float64 = self.avPlayerViewController.player!.currentTime().seconds;&lt;br /&gt;
                let pos = Int64(time);&lt;br /&gt;
                NSLog(&amp;quot;New Elapse Time = \(time)&amp;quot;);&lt;br /&gt;
                self.nielsenAppApi?.playheadPosition(pos);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void setPlayheadPosition(long position)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== stop ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void) stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== end ===&lt;br /&gt;
When content stop is initiated and content cannot be resumed from the same position (it can only be restarted from the beginning of stream).&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;- (void) end;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Privacy and Opt-Out ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
&lt;br /&gt;
iOS| &lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL for the Nielsen Privacy web page should be retrieved from the optOutURL property of the SDK object &amp;lt;code&amp;gt;optOutURL&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL in the optOutURL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- === Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = nAppApiObject.optOutURL;&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Android = &lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking &amp;lt;code&amp;gt;userOptOutURLString()&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public String userOptOutURLString()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the &amp;lt;code&amp;gt; getOptOutStatus() &amp;lt;/code&amp;gt; method.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean getOptOutStatus()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make one update to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;iOS Example:&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
            &amp;quot;appid&amp;quot;: &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Android Example:&amp;lt;/big&amp;gt;''' &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2467</id>
		<title>DCR Italy Video App SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2467"/>
		<updated>2018-02-15T15:44:04Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK:''' The Nielsen SDK package contains a variety of sample players for your reference.&lt;br /&gt;
If you do not have any of these prerequisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] guide for information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
==  Implementation ==&lt;br /&gt;
This guide covers implementation steps for iOS using Xcode and Android using Android Studio.&lt;br /&gt;
&lt;br /&gt;
== Setting up your  Development Environment  ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
xCode|&lt;br /&gt;
&amp;lt;big&amp;gt;&lt;br /&gt;
'''Configuring Xcode Development Environment''' &lt;br /&gt;
&amp;lt;/big&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 9.0 and above.&lt;br /&gt;
&lt;br /&gt;
The SDK uses the NSURLSession instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': All communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Importing Frameworks'''&amp;lt;/big&amp;gt;&lt;br /&gt;
The first step is to ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Swift'''&amp;lt;/big&amp;gt;&lt;br /&gt;
To import a set of Objective-C files in the same app target as your Swift code, you rely on an Objective-C bridging header to expose those files to Swift. Xcode offers to create this header file when you add a Swift file to an existing Objective-C app, or an Objective-C file to an existing Swift app.&lt;br /&gt;
&lt;br /&gt;
Select File/New File/Objective-C File  &amp;lt;br /&amp;gt;&lt;br /&gt;
Xcode will prompt you to create a bridging header.&lt;br /&gt;
[[File:bridgingheader 2x.png|600px|center|link=]] &amp;lt;br /&amp;gt;&lt;br /&gt;
Once this file has been created, you need to add the following:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Objective-C'''&amp;lt;/big&amp;gt;&lt;br /&gt;
Add the code &lt;br /&gt;
&amp;lt;syntaxhighlight lang =&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 to the View Controller’s header file.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
|Android =&lt;br /&gt;
&amp;lt;big&amp;gt;'''Configuring Android Development Environment'''&amp;lt;/big&amp;gt;'&lt;br /&gt;
*The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package.&lt;br /&gt;
&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Library'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Classes/package&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== SDK Initialization ==&lt;br /&gt;
The latest version of the Nielsen App SDK allows instantiating multiple instances of the SDK object, which can be used simultaneously without any issue. The sharedInstance API that creates a singleton object was deprecated prior to version 5.1.1. (Version 4.0 for Android)&lt;br /&gt;
&lt;br /&gt;
* A maximum of four SDK instances per appid are supported. When a fifth SDK instance is launched, the SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
* When four SDK instances exist, you must destroy an old instance before creating a new one.&lt;br /&gt;
&lt;br /&gt;
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.&lt;br /&gt;
&lt;br /&gt;
* The appid is provided by the Nielsen Technical Account Manager (TAM). The appid is a GUID data type and is specific to the application.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter / Argument !! Description !! Source !! Required? !! Example&lt;br /&gt;
|-&lt;br /&gt;
| appid || Unique id for the application assigned by Nielsen. It is GUID data type.|| Nielsen-specified || Yes || PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&lt;br /&gt;
|-&lt;br /&gt;
| appname || Name of the application || Client-defined || No|| Nielsen Sample App&lt;br /&gt;
|-&lt;br /&gt;
| appversion || Current version of the app used || Client-defined || No || &amp;quot;1.0.2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Nielsen collection facility to which the SDK should connect.&lt;br /&gt;
'''Italian Clients'''&lt;br /&gt;
* &amp;quot;it&amp;quot;&lt;br /&gt;
|| Nielsen-specified || Yes || &amp;quot;it&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || Enables Nielsen console logging. Only required for testing&lt;br /&gt;
|| Nielsen-specified || Optional || &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==== Sample SDK Initialization Code ====&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift  = &lt;br /&gt;
Swift 4.0 Example:&lt;br /&gt;
&amp;lt;code&amp;gt;NielsenInit.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
           &amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
            &amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
            &amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
            &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sample code using AVPlayer.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ViewController.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class ViewController: UIViewController, NielsenAppApiDelegate, AVPictureInPictureControllerDelegate, CLLocationManagerDelegate  {&lt;br /&gt;
    &lt;br /&gt;
    let avPlayerViewController = AVPlayerViewController()&lt;br /&gt;
    var avPlayer:AVPlayer?&lt;br /&gt;
    var nielsenAppApi: NielsenAppApi!&lt;br /&gt;
&lt;br /&gt;
  override func viewDidLoad() {&lt;br /&gt;
        super.viewDidLoad()&lt;br /&gt;
&lt;br /&gt;
self.nielsenAppApi = NielsenInit.createNielsenAppApi(delegate: self)&lt;br /&gt;
NSLog(&amp;quot;Nielsen SDK initialized&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Objective C = &lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;    &lt;br /&gt;
#import &amp;quot;NlsAppApiFactory.h&amp;quot;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@implementation NlsAppApiFactory&lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
{&lt;br /&gt;
    NSDictionary *appInformation = @{&lt;br /&gt;
                                     @&amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot;&lt;br /&gt;
                                     };&lt;br /&gt;
    return [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&lt;br /&gt;
}&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following would be the &amp;lt;code&amp;gt;NlsAppApiFactory.h&amp;lt;/code&amp;gt; file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@class NielsenAppApi;&lt;br /&gt;
@protocol NielsenAppApiDeligate;&lt;br /&gt;
&lt;br /&gt;
@interface NlsAppApiFactory : NSObject &lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppAPI *) createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appversion&amp;quot;, &amp;quot;1.0&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;DEBUG&amp;quot;); // only for debug builds&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&amp;lt;br /&amp;gt;&lt;br /&gt;
* Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== APP SDK Error &amp;amp; Event Codes ==&lt;br /&gt;
To view the Error and Event codes for iOS and Android, please review the [[APP SDK Event Codes|App SDK Event Code]] Reference page.&lt;br /&gt;
== Configure Payload ==&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift = &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
       let channelInfo = [&lt;br /&gt;
            &amp;quot;channelName&amp;quot;: &amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
        &lt;br /&gt;
        let contentMetadata = [&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
                &amp;quot;assetid&amp;quot;: &amp;quot;88675545&amp;quot;,&lt;br /&gt;
                &amp;quot;title&amp;quot;: &amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
                &amp;quot;isfullepisode&amp;quot;:&amp;quot;n&amp;quot;,&lt;br /&gt;
                &amp;quot;adloadtype&amp;quot;:&amp;quot;2&amp;quot;,&lt;br /&gt;
                &amp;quot;program&amp;quot;:&amp;quot;Program Name&amp;quot;,&lt;br /&gt;
                &amp;quot;length&amp;quot;:&amp;quot;3600&amp;quot;, &lt;br /&gt;
                &amp;quot;airdate&amp;quot;:&amp;quot;20171020 10:05:00&amp;quot;&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;     &lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt; &lt;br /&gt;
NSDictionary  *channelInfo = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;channelName&amp;quot;:@&amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
NSDictionary *contentMetadata = @&lt;br /&gt;
  {@&amp;quot;type&amp;quot;: @&amp;quot;content&amp;quot;,&lt;br /&gt;
  @&amp;quot;assetid&amp;quot;: [NSString stringWithFormat:@&amp;quot;ProgramAssetId-%d&amp;quot;, i],&lt;br /&gt;
  @&amp;quot;length&amp;quot;: @&amp;quot;3600&amp;quot;,&lt;br /&gt;
  @&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;title&amp;quot;: @&amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
  @&amp;quot;isfullepisode&amp;quot;: @&amp;quot;y&amp;quot;,&lt;br /&gt;
  @&amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
  @&amp;quot;airdate&amp;quot;: &amp;quot;20161013 20:00:00&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject channelInfo = new JSONObject()&lt;br /&gt;
    .put(&amp;quot;channelname&amp;quot;,&amp;quot;My Channel Name 1&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
JSONObject contentMetadata = new JSONObject()&lt;br /&gt;
//SDK Metadata&lt;br /&gt;
    .put(&amp;quot;type&amp;quot;, &amp;quot;content&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;assetid&amp;quot;, &amp;quot;vid345-67483&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;title&amp;quot;, &amp;quot;Program S3, EP1&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;length&amp;quot;, &amp;quot;3600&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;isfullepisode&amp;quot;, &amp;quot;y&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;adloadtype&amp;quot;, &amp;quot;2&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;airdate&amp;quot;, &amp;quot;20161013 20:00:00&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;   &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Configure metadata === &lt;br /&gt;
Configure metadata should remain constant throughout the completion of an episode or live stream.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| channelName	|| Any string representing the channel/stream	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Content metadata ===&lt;br /&gt;
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| program ||name of program (25 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| title ||name of program (40 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || Yes&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || Yes&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches TV ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || Yes&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
The ad metadata (if applicable) should be passed for each individual ad, if ads are available during or before the stream begins.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Configure API Calls ==&lt;br /&gt;
=== Sample API Sequence ===&lt;br /&gt;
A Sample API sequence could follow this flow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
|On App Start||&amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadata];&amp;lt;/code&amp;gt; || // contentMetadata Object contains the JSON metadata for the impression&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;[nielsenMeter play: channelName];&amp;lt;/code&amp;gt; || // channelName contains JSON metadata of channel/video name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadataObject];&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;[nielsenMeter end];&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
=== Life cycle of SDK instance ===&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[DCR_Video_APP_SDK#play|play]] and [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[DCR_Video_APP_SDK#stop|stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[DCR_Video_APP_SDK#end|end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## &amp;lt;code&amp;gt;appDisableApi&amp;lt;/code&amp;gt; is called&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (assign) BOOL appDisableApi;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] and  [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence of Calls ===&lt;br /&gt;
=== play ===&lt;br /&gt;
Use [[DCR_Video_APP_SDK#play|play]] to pass the channel descriptor information through channelName parameter when the user taps the '''Play''' button on the player.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;   [nielsenAppApi play:(JSONObject channelInfo)];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;    public void play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;nielsenAppApi?.play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void)loadMetadata:(id)contentMetadata;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void loadMetadata(JSONObject contentMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.loadMetadata(contentMetadata)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== playheadPosition ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void) playheadPosition: (long long) playheadPos&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Sending playheadposition for content ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
AVPlayer *player;&lt;br /&gt;
CMTime curTime=[player currentTime];&lt;br /&gt;
int pos = CMTimeGetSeconds(curTime);&lt;br /&gt;
[nAppApiObject playheadPosition:pos];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
        //Monitor the Playhead position of the AVPlayer&lt;br /&gt;
        let timeInterval: CMTime = CMTimeMakeWithSeconds(1.0,10)&lt;br /&gt;
        self.avPlayerViewController.player?.addPeriodicTimeObserver(forInterval: timeInterval, queue: DispatchQueue.main) {(elapsedTime: CMTime) -&amp;gt; Void in&lt;br /&gt;
            if self.avPlayerViewController.player!.currentItem?.status == .readyToPlay {&lt;br /&gt;
                let time : Float64 = self.avPlayerViewController.player!.currentTime().seconds;&lt;br /&gt;
                let pos = Int64(time);&lt;br /&gt;
                NSLog(&amp;quot;New Elapse Time = \(time)&amp;quot;);&lt;br /&gt;
                self.nielsenAppApi?.playheadPosition(pos);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void setPlayheadPosition(long position)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== stop ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void) stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== end ===&lt;br /&gt;
When content stop is initiated and content cannot be resumed from the same position (it can only be restarted from the beginning of stream).&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;- (void) end;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Privacy and Opt-Out ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
&lt;br /&gt;
iOS| &lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL for the Nielsen Privacy web page should be retrieved from the optOutURL property of the SDK object &amp;lt;code&amp;gt;optOutURL&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL in the optOutURL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- === Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = nAppApiObject.optOutURL;&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Android = &lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking &amp;lt;code&amp;gt;userOptOutURLString()&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public String userOptOutURLString()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the &amp;lt;code&amp;gt; getOptOutStatus() &amp;lt;/code&amp;gt; method.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean getOptOutStatus()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make one update to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;iOS Example:&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
            &amp;quot;appid&amp;quot;: &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Android Example:&amp;lt;/big&amp;gt;''' &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2466</id>
		<title>DCR Italy Video App SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2466"/>
		<updated>2018-02-15T15:39:44Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: /* Privacy and Opt-Out */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK:''' The Nielsen SDK package contains a variety of sample players for your reference.&lt;br /&gt;
If you do not have any of these prerequisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] guide for information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
==  Implementation ==&lt;br /&gt;
This guide covers implementation steps for iOS using Xcode and Android using Android Studio.&lt;br /&gt;
&lt;br /&gt;
== Setting up your  Development Environment  ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
xCode|&lt;br /&gt;
&amp;lt;big&amp;gt;&lt;br /&gt;
'''Configuring Xcode Development Environment''' &lt;br /&gt;
&amp;lt;/big&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 9.0 and above.&lt;br /&gt;
&lt;br /&gt;
The SDK uses the NSURLSession instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': All communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Importing Frameworks'''&amp;lt;/big&amp;gt;&lt;br /&gt;
The first step is to ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Swift'''&amp;lt;/big&amp;gt;&lt;br /&gt;
To import a set of Objective-C files in the same app target as your Swift code, you rely on an Objective-C bridging header to expose those files to Swift. Xcode offers to create this header file when you add a Swift file to an existing Objective-C app, or an Objective-C file to an existing Swift app.&lt;br /&gt;
&lt;br /&gt;
Select File/New File/Objective-C File  &amp;lt;br /&amp;gt;&lt;br /&gt;
Xcode will prompt you to create a bridging header.&lt;br /&gt;
[[File:bridgingheader 2x.png|600px|center|link=]] &amp;lt;br /&amp;gt;&lt;br /&gt;
Once this file has been created, you need to add the following:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Objective-C'''&amp;lt;/big&amp;gt;&lt;br /&gt;
Add the code &lt;br /&gt;
&amp;lt;syntaxhighlight lang =&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 to the View Controller’s header file.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
|Android =&lt;br /&gt;
&amp;lt;big&amp;gt;'''Configuring Android Development Environment'''&amp;lt;/big&amp;gt;'&lt;br /&gt;
*The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package.&lt;br /&gt;
&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Library'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Classes/package&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== SDK Initialization ==&lt;br /&gt;
The latest version of the Nielsen App SDK allows instantiating multiple instances of the SDK object, which can be used simultaneously without any issue. The sharedInstance API that creates a singleton object was deprecated prior to version 5.1.1. (Version 4.0 for Android)&lt;br /&gt;
&lt;br /&gt;
* A maximum of four SDK instances per appid are supported. When a fifth SDK instance is launched, the SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
* When four SDK instances exist, you must destroy an old instance before creating a new one.&lt;br /&gt;
&lt;br /&gt;
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.&lt;br /&gt;
&lt;br /&gt;
* The appid is provided by the Nielsen Technical Account Manager (TAM). The appid is a GUID data type and is specific to the application.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter / Argument !! Description !! Source !! Required? !! Example&lt;br /&gt;
|-&lt;br /&gt;
| appid || Unique id for the application assigned by Nielsen. It is GUID data type.|| Nielsen-specified || Yes || PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&lt;br /&gt;
|-&lt;br /&gt;
| appname || Name of the application || Client-defined || No|| Nielsen Sample App&lt;br /&gt;
|-&lt;br /&gt;
| appversion || Current version of the app used || Client-defined || No || &amp;quot;1.0.2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Nielsen collection facility to which the SDK should connect.&lt;br /&gt;
'''Italian Clients'''&lt;br /&gt;
* &amp;quot;it&amp;quot;&lt;br /&gt;
|| Nielsen-specified || Yes || &amp;quot;it&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || Enables Nielsen console logging. Only required for testing&lt;br /&gt;
|| Nielsen-specified || Optional || &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==== Sample SDK Initialization Code ====&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift  = &lt;br /&gt;
Swift 4.0 Example:&lt;br /&gt;
&amp;lt;code&amp;gt;NielsenInit.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
           &amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
            &amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
            &amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
            &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sample code using AVPlayer.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ViewController.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class ViewController: UIViewController, NielsenAppApiDelegate, AVPictureInPictureControllerDelegate, CLLocationManagerDelegate  {&lt;br /&gt;
    &lt;br /&gt;
    let avPlayerViewController = AVPlayerViewController()&lt;br /&gt;
    var avPlayer:AVPlayer?&lt;br /&gt;
    var nielsenAppApi: NielsenAppApi!&lt;br /&gt;
&lt;br /&gt;
  override func viewDidLoad() {&lt;br /&gt;
        super.viewDidLoad()&lt;br /&gt;
&lt;br /&gt;
self.nielsenAppApi = NielsenInit.createNielsenAppApi(delegate: self)&lt;br /&gt;
NSLog(&amp;quot;Nielsen SDK initialized&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Objective C = &lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;    &lt;br /&gt;
#import &amp;quot;NlsAppApiFactory.h&amp;quot;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@implementation NlsAppApiFactory&lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
{&lt;br /&gt;
    NSDictionary *appInformation = @{&lt;br /&gt;
                                     @&amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot;&lt;br /&gt;
                                     };&lt;br /&gt;
    return [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&lt;br /&gt;
}&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following would be the &amp;lt;code&amp;gt;NlsAppApiFactory.h&amp;lt;/code&amp;gt; file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@class NielsenAppApi;&lt;br /&gt;
@protocol NielsenAppApiDeligate;&lt;br /&gt;
&lt;br /&gt;
@interface NlsAppApiFactory : NSObject &lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppAPI *) createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appversion&amp;quot;, &amp;quot;1.0&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;DEBUG&amp;quot;); // only for debug builds&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&amp;lt;br /&amp;gt;&lt;br /&gt;
* Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== APP SDK Error &amp;amp; Event Codes ==&lt;br /&gt;
To view the Error and Event codes for iOS and Android, please review the [[APP SDK Event Codes|App SDK Event Code]] Reference page.&lt;br /&gt;
== Configure Payload ==&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift = &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
       let channelInfo = [&lt;br /&gt;
            &amp;quot;channelName&amp;quot;: &amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
        &lt;br /&gt;
        let contentMetadata = [&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
                &amp;quot;assetid&amp;quot;: &amp;quot;88675545&amp;quot;,&lt;br /&gt;
                &amp;quot;title&amp;quot;: &amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
                &amp;quot;isfullepisode&amp;quot;:&amp;quot;n&amp;quot;,&lt;br /&gt;
                &amp;quot;adloadtype&amp;quot;:&amp;quot;2&amp;quot;,&lt;br /&gt;
                &amp;quot;program&amp;quot;:&amp;quot;Program Name&amp;quot;,&lt;br /&gt;
                &amp;quot;length&amp;quot;:&amp;quot;3600&amp;quot;, &lt;br /&gt;
                &amp;quot;airdate&amp;quot;:&amp;quot;20171020 10:05:00&amp;quot;&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;     &lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt; &lt;br /&gt;
NSDictionary  *channelInfo = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;channelName&amp;quot;:@&amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
NSDictionary *contentMetadata = @&lt;br /&gt;
  {@&amp;quot;type&amp;quot;: @&amp;quot;content&amp;quot;,&lt;br /&gt;
  @&amp;quot;assetid&amp;quot;: [NSString stringWithFormat:@&amp;quot;ProgramAssetId-%d&amp;quot;, i],&lt;br /&gt;
  @&amp;quot;length&amp;quot;: @&amp;quot;3600&amp;quot;,&lt;br /&gt;
  @&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;title&amp;quot;: @&amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
  @&amp;quot;isfullepisode&amp;quot;: @&amp;quot;y&amp;quot;,&lt;br /&gt;
  @&amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
  @&amp;quot;airdate&amp;quot;: &amp;quot;20161013 20:00:00&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject channelInfo = new JSONObject()&lt;br /&gt;
    .put(&amp;quot;channelname&amp;quot;,&amp;quot;My Channel Name 1&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
JSONObject contentMetadata = new JSONObject()&lt;br /&gt;
//SDK Metadata&lt;br /&gt;
    .put(&amp;quot;type&amp;quot;, &amp;quot;content&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;assetid&amp;quot;, &amp;quot;vid345-67483&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;title&amp;quot;, &amp;quot;Program S3, EP1&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;length&amp;quot;, &amp;quot;3600&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;isfullepisode&amp;quot;, &amp;quot;y&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;adloadtype&amp;quot;, &amp;quot;2&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;airdate&amp;quot;, &amp;quot;20161013 20:00:00&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;   &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Configure metadata === &lt;br /&gt;
Configure metadata should remain constant throughout the completion of an episode or live stream.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| channelName	|| Any string representing the channel/stream	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Content metadata ===&lt;br /&gt;
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| program ||name of program (25 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| title ||name of program (40 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || Yes&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || Yes&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches TV ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || Yes&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
The ad metadata (if applicable) should be passed for each individual ad, if ads are available during or before the stream begins.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Configure API Calls ==&lt;br /&gt;
=== Sample API Sequence ===&lt;br /&gt;
A Sample API sequence could follow this flow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
|On App Start||&amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadata];&amp;lt;/code&amp;gt; || // contentMetadata Object contains the JSON metadata for the impression&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;[nielsenMeter play: channelName];&amp;lt;/code&amp;gt; || // channelName contains JSON metadata of channel/video name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadataObject];&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;[nielsenMeter end];&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
=== Life cycle of SDK instance ===&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[DCR_Video_APP_SDK#play|play]] and [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[DCR_Video_APP_SDK#stop|stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[DCR_Video_APP_SDK#end|end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## &amp;lt;code&amp;gt;appDisableApi&amp;lt;/code&amp;gt; is called&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (assign) BOOL appDisableApi;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] and  [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence of Calls ===&lt;br /&gt;
=== play ===&lt;br /&gt;
Use [[DCR_Video_APP_SDK#play|play]] to pass the channel descriptor information through channelName parameter when the user taps the '''Play''' button on the player.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;   [nielsenAppApi play:(JSONObject channelInfo)];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;    public void play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;nielsenAppApi?.play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void)loadMetadata:(id)contentMetadata;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void loadMetadata(JSONObject contentMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.loadMetadata(contentMetadata)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== playheadPosition ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void) playheadPosition: (long long) playheadPos&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Sending playheadposition for content ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
AVPlayer *player;&lt;br /&gt;
CMTime curTime=[player currentTime];&lt;br /&gt;
int pos = CMTimeGetSeconds(curTime);&lt;br /&gt;
[nAppApiObject playheadPosition:pos];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
        //Monitor the Playhead position of the AVPlayer&lt;br /&gt;
        let timeInterval: CMTime = CMTimeMakeWithSeconds(1.0,10)&lt;br /&gt;
        self.avPlayerViewController.player?.addPeriodicTimeObserver(forInterval: timeInterval, queue: DispatchQueue.main) {(elapsedTime: CMTime) -&amp;gt; Void in&lt;br /&gt;
            if self.avPlayerViewController.player!.currentItem?.status == .readyToPlay {&lt;br /&gt;
                let time : Float64 = self.avPlayerViewController.player!.currentTime().seconds;&lt;br /&gt;
                let pos = Int64(time);&lt;br /&gt;
                NSLog(&amp;quot;New Elapse Time = \(time)&amp;quot;);&lt;br /&gt;
                self.nielsenAppApi?.playheadPosition(pos);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void setPlayheadPosition(long position)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== stop ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void) stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== end ===&lt;br /&gt;
When content stop is initiated and content cannot be resumed from the same position (it can only be restarted from the beginning of stream).&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;- (void) end;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Privacy and Opt-Out ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
&lt;br /&gt;
iOS| &lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL for the Nielsen Privacy web page should be retrieved from the optOutURL property of the SDK object &amp;lt;code&amp;gt;optOutURL&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL in the optOutURL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- === Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = nAppApiObject.optOutURL;&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy App.png|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Android = &lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking &amp;lt;code&amp;gt;userOptOutURLString()&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public String userOptOutURLString()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the &amp;lt;code&amp;gt; getOptOutStatus() &amp;lt;/code&amp;gt; method.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean getOptOutStatus()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make one update to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;iOS Example:&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
            &amp;quot;appid&amp;quot;: &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Android Example:&amp;lt;/big&amp;gt;''' &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2465</id>
		<title>DCR Italy Video App SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2465"/>
		<updated>2018-02-15T15:25:57Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: /* Privacy and Opt-Out */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK:''' The Nielsen SDK package contains a variety of sample players for your reference.&lt;br /&gt;
If you do not have any of these prerequisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] guide for information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
==  Implementation ==&lt;br /&gt;
This guide covers implementation steps for iOS using Xcode and Android using Android Studio.&lt;br /&gt;
&lt;br /&gt;
== Setting up your  Development Environment  ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
xCode|&lt;br /&gt;
&amp;lt;big&amp;gt;&lt;br /&gt;
'''Configuring Xcode Development Environment''' &lt;br /&gt;
&amp;lt;/big&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 9.0 and above.&lt;br /&gt;
&lt;br /&gt;
The SDK uses the NSURLSession instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': All communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Importing Frameworks'''&amp;lt;/big&amp;gt;&lt;br /&gt;
The first step is to ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Swift'''&amp;lt;/big&amp;gt;&lt;br /&gt;
To import a set of Objective-C files in the same app target as your Swift code, you rely on an Objective-C bridging header to expose those files to Swift. Xcode offers to create this header file when you add a Swift file to an existing Objective-C app, or an Objective-C file to an existing Swift app.&lt;br /&gt;
&lt;br /&gt;
Select File/New File/Objective-C File  &amp;lt;br /&amp;gt;&lt;br /&gt;
Xcode will prompt you to create a bridging header.&lt;br /&gt;
[[File:bridgingheader 2x.png|600px|center|link=]] &amp;lt;br /&amp;gt;&lt;br /&gt;
Once this file has been created, you need to add the following:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Objective-C'''&amp;lt;/big&amp;gt;&lt;br /&gt;
Add the code &lt;br /&gt;
&amp;lt;syntaxhighlight lang =&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 to the View Controller’s header file.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
|Android =&lt;br /&gt;
&amp;lt;big&amp;gt;'''Configuring Android Development Environment'''&amp;lt;/big&amp;gt;'&lt;br /&gt;
*The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package.&lt;br /&gt;
&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Library'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Classes/package&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== SDK Initialization ==&lt;br /&gt;
The latest version of the Nielsen App SDK allows instantiating multiple instances of the SDK object, which can be used simultaneously without any issue. The sharedInstance API that creates a singleton object was deprecated prior to version 5.1.1. (Version 4.0 for Android)&lt;br /&gt;
&lt;br /&gt;
* A maximum of four SDK instances per appid are supported. When a fifth SDK instance is launched, the SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
* When four SDK instances exist, you must destroy an old instance before creating a new one.&lt;br /&gt;
&lt;br /&gt;
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.&lt;br /&gt;
&lt;br /&gt;
* The appid is provided by the Nielsen Technical Account Manager (TAM). The appid is a GUID data type and is specific to the application.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter / Argument !! Description !! Source !! Required? !! Example&lt;br /&gt;
|-&lt;br /&gt;
| appid || Unique id for the application assigned by Nielsen. It is GUID data type.|| Nielsen-specified || Yes || PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&lt;br /&gt;
|-&lt;br /&gt;
| appname || Name of the application || Client-defined || No|| Nielsen Sample App&lt;br /&gt;
|-&lt;br /&gt;
| appversion || Current version of the app used || Client-defined || No || &amp;quot;1.0.2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Nielsen collection facility to which the SDK should connect.&lt;br /&gt;
'''Italian Clients'''&lt;br /&gt;
* &amp;quot;it&amp;quot;&lt;br /&gt;
|| Nielsen-specified || Yes || &amp;quot;it&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || Enables Nielsen console logging. Only required for testing&lt;br /&gt;
|| Nielsen-specified || Optional || &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==== Sample SDK Initialization Code ====&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift  = &lt;br /&gt;
Swift 4.0 Example:&lt;br /&gt;
&amp;lt;code&amp;gt;NielsenInit.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
           &amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
            &amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
            &amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
            &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sample code using AVPlayer.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ViewController.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class ViewController: UIViewController, NielsenAppApiDelegate, AVPictureInPictureControllerDelegate, CLLocationManagerDelegate  {&lt;br /&gt;
    &lt;br /&gt;
    let avPlayerViewController = AVPlayerViewController()&lt;br /&gt;
    var avPlayer:AVPlayer?&lt;br /&gt;
    var nielsenAppApi: NielsenAppApi!&lt;br /&gt;
&lt;br /&gt;
  override func viewDidLoad() {&lt;br /&gt;
        super.viewDidLoad()&lt;br /&gt;
&lt;br /&gt;
self.nielsenAppApi = NielsenInit.createNielsenAppApi(delegate: self)&lt;br /&gt;
NSLog(&amp;quot;Nielsen SDK initialized&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Objective C = &lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;    &lt;br /&gt;
#import &amp;quot;NlsAppApiFactory.h&amp;quot;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@implementation NlsAppApiFactory&lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
{&lt;br /&gt;
    NSDictionary *appInformation = @{&lt;br /&gt;
                                     @&amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot;&lt;br /&gt;
                                     };&lt;br /&gt;
    return [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&lt;br /&gt;
}&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following would be the &amp;lt;code&amp;gt;NlsAppApiFactory.h&amp;lt;/code&amp;gt; file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@class NielsenAppApi;&lt;br /&gt;
@protocol NielsenAppApiDeligate;&lt;br /&gt;
&lt;br /&gt;
@interface NlsAppApiFactory : NSObject &lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppAPI *) createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appversion&amp;quot;, &amp;quot;1.0&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;DEBUG&amp;quot;); // only for debug builds&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&amp;lt;br /&amp;gt;&lt;br /&gt;
* Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== APP SDK Error &amp;amp; Event Codes ==&lt;br /&gt;
To view the Error and Event codes for iOS and Android, please review the [[APP SDK Event Codes|App SDK Event Code]] Reference page.&lt;br /&gt;
== Configure Payload ==&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift = &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
       let channelInfo = [&lt;br /&gt;
            &amp;quot;channelName&amp;quot;: &amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
        &lt;br /&gt;
        let contentMetadata = [&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
                &amp;quot;assetid&amp;quot;: &amp;quot;88675545&amp;quot;,&lt;br /&gt;
                &amp;quot;title&amp;quot;: &amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
                &amp;quot;isfullepisode&amp;quot;:&amp;quot;n&amp;quot;,&lt;br /&gt;
                &amp;quot;adloadtype&amp;quot;:&amp;quot;2&amp;quot;,&lt;br /&gt;
                &amp;quot;program&amp;quot;:&amp;quot;Program Name&amp;quot;,&lt;br /&gt;
                &amp;quot;length&amp;quot;:&amp;quot;3600&amp;quot;, &lt;br /&gt;
                &amp;quot;airdate&amp;quot;:&amp;quot;20171020 10:05:00&amp;quot;&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;     &lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt; &lt;br /&gt;
NSDictionary  *channelInfo = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;channelName&amp;quot;:@&amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
NSDictionary *contentMetadata = @&lt;br /&gt;
  {@&amp;quot;type&amp;quot;: @&amp;quot;content&amp;quot;,&lt;br /&gt;
  @&amp;quot;assetid&amp;quot;: [NSString stringWithFormat:@&amp;quot;ProgramAssetId-%d&amp;quot;, i],&lt;br /&gt;
  @&amp;quot;length&amp;quot;: @&amp;quot;3600&amp;quot;,&lt;br /&gt;
  @&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;title&amp;quot;: @&amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
  @&amp;quot;isfullepisode&amp;quot;: @&amp;quot;y&amp;quot;,&lt;br /&gt;
  @&amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
  @&amp;quot;airdate&amp;quot;: &amp;quot;20161013 20:00:00&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject channelInfo = new JSONObject()&lt;br /&gt;
    .put(&amp;quot;channelname&amp;quot;,&amp;quot;My Channel Name 1&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
JSONObject contentMetadata = new JSONObject()&lt;br /&gt;
//SDK Metadata&lt;br /&gt;
    .put(&amp;quot;type&amp;quot;, &amp;quot;content&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;assetid&amp;quot;, &amp;quot;vid345-67483&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;title&amp;quot;, &amp;quot;Program S3, EP1&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;length&amp;quot;, &amp;quot;3600&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;isfullepisode&amp;quot;, &amp;quot;y&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;adloadtype&amp;quot;, &amp;quot;2&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;airdate&amp;quot;, &amp;quot;20161013 20:00:00&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;   &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Configure metadata === &lt;br /&gt;
Configure metadata should remain constant throughout the completion of an episode or live stream.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| channelName	|| Any string representing the channel/stream	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Content metadata ===&lt;br /&gt;
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| program ||name of program (25 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| title ||name of program (40 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || Yes&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || Yes&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches TV ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || Yes&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
The ad metadata (if applicable) should be passed for each individual ad, if ads are available during or before the stream begins.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Configure API Calls ==&lt;br /&gt;
=== Sample API Sequence ===&lt;br /&gt;
A Sample API sequence could follow this flow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
|On App Start||&amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadata];&amp;lt;/code&amp;gt; || // contentMetadata Object contains the JSON metadata for the impression&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;[nielsenMeter play: channelName];&amp;lt;/code&amp;gt; || // channelName contains JSON metadata of channel/video name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadataObject];&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;[nielsenMeter end];&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
=== Life cycle of SDK instance ===&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[DCR_Video_APP_SDK#play|play]] and [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[DCR_Video_APP_SDK#stop|stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[DCR_Video_APP_SDK#end|end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## &amp;lt;code&amp;gt;appDisableApi&amp;lt;/code&amp;gt; is called&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (assign) BOOL appDisableApi;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] and  [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence of Calls ===&lt;br /&gt;
=== play ===&lt;br /&gt;
Use [[DCR_Video_APP_SDK#play|play]] to pass the channel descriptor information through channelName parameter when the user taps the '''Play''' button on the player.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;   [nielsenAppApi play:(JSONObject channelInfo)];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;    public void play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;nielsenAppApi?.play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void)loadMetadata:(id)contentMetadata;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void loadMetadata(JSONObject contentMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.loadMetadata(contentMetadata)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== playheadPosition ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void) playheadPosition: (long long) playheadPos&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Sending playheadposition for content ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
AVPlayer *player;&lt;br /&gt;
CMTime curTime=[player currentTime];&lt;br /&gt;
int pos = CMTimeGetSeconds(curTime);&lt;br /&gt;
[nAppApiObject playheadPosition:pos];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
        //Monitor the Playhead position of the AVPlayer&lt;br /&gt;
        let timeInterval: CMTime = CMTimeMakeWithSeconds(1.0,10)&lt;br /&gt;
        self.avPlayerViewController.player?.addPeriodicTimeObserver(forInterval: timeInterval, queue: DispatchQueue.main) {(elapsedTime: CMTime) -&amp;gt; Void in&lt;br /&gt;
            if self.avPlayerViewController.player!.currentItem?.status == .readyToPlay {&lt;br /&gt;
                let time : Float64 = self.avPlayerViewController.player!.currentTime().seconds;&lt;br /&gt;
                let pos = Int64(time);&lt;br /&gt;
                NSLog(&amp;quot;New Elapse Time = \(time)&amp;quot;);&lt;br /&gt;
                self.nielsenAppApi?.playheadPosition(pos);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void setPlayheadPosition(long position)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== stop ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void) stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== end ===&lt;br /&gt;
When content stop is initiated and content cannot be resumed from the same position (it can only be restarted from the beginning of stream).&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;- (void) end;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Privacy and Opt-Out ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
&lt;br /&gt;
iOS| &lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL for the Nielsen Privacy web page should be retrieved from the optOutURL property of the SDK object &amp;lt;code&amp;gt;optOutURL&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL in the optOutURL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- === Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = nAppApiObject.optOutURL;&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy App.png|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy App.png|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Android = &lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking &amp;lt;code&amp;gt;userOptOutURLString()&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public String userOptOutURLString()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the &amp;lt;code&amp;gt; getOptOutStatus() &amp;lt;/code&amp;gt; method.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean getOptOutStatus()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make one update to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;iOS Example:&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
            &amp;quot;appid&amp;quot;: &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Android Example:&amp;lt;/big&amp;gt;''' &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2464</id>
		<title>DCR Italy Video App SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2464"/>
		<updated>2018-02-15T15:04:59Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: /* Privacy and Opt-Out */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK:''' The Nielsen SDK package contains a variety of sample players for your reference.&lt;br /&gt;
If you do not have any of these prerequisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] guide for information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
==  Implementation ==&lt;br /&gt;
This guide covers implementation steps for iOS using Xcode and Android using Android Studio.&lt;br /&gt;
&lt;br /&gt;
== Setting up your  Development Environment  ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
xCode|&lt;br /&gt;
&amp;lt;big&amp;gt;&lt;br /&gt;
'''Configuring Xcode Development Environment''' &lt;br /&gt;
&amp;lt;/big&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 9.0 and above.&lt;br /&gt;
&lt;br /&gt;
The SDK uses the NSURLSession instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': All communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Importing Frameworks'''&amp;lt;/big&amp;gt;&lt;br /&gt;
The first step is to ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Swift'''&amp;lt;/big&amp;gt;&lt;br /&gt;
To import a set of Objective-C files in the same app target as your Swift code, you rely on an Objective-C bridging header to expose those files to Swift. Xcode offers to create this header file when you add a Swift file to an existing Objective-C app, or an Objective-C file to an existing Swift app.&lt;br /&gt;
&lt;br /&gt;
Select File/New File/Objective-C File  &amp;lt;br /&amp;gt;&lt;br /&gt;
Xcode will prompt you to create a bridging header.&lt;br /&gt;
[[File:bridgingheader 2x.png|600px|center|link=]] &amp;lt;br /&amp;gt;&lt;br /&gt;
Once this file has been created, you need to add the following:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Objective-C'''&amp;lt;/big&amp;gt;&lt;br /&gt;
Add the code &lt;br /&gt;
&amp;lt;syntaxhighlight lang =&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 to the View Controller’s header file.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
|Android =&lt;br /&gt;
&amp;lt;big&amp;gt;'''Configuring Android Development Environment'''&amp;lt;/big&amp;gt;'&lt;br /&gt;
*The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package.&lt;br /&gt;
&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Library'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Classes/package&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== SDK Initialization ==&lt;br /&gt;
The latest version of the Nielsen App SDK allows instantiating multiple instances of the SDK object, which can be used simultaneously without any issue. The sharedInstance API that creates a singleton object was deprecated prior to version 5.1.1. (Version 4.0 for Android)&lt;br /&gt;
&lt;br /&gt;
* A maximum of four SDK instances per appid are supported. When a fifth SDK instance is launched, the SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
* When four SDK instances exist, you must destroy an old instance before creating a new one.&lt;br /&gt;
&lt;br /&gt;
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.&lt;br /&gt;
&lt;br /&gt;
* The appid is provided by the Nielsen Technical Account Manager (TAM). The appid is a GUID data type and is specific to the application.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter / Argument !! Description !! Source !! Required? !! Example&lt;br /&gt;
|-&lt;br /&gt;
| appid || Unique id for the application assigned by Nielsen. It is GUID data type.|| Nielsen-specified || Yes || PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&lt;br /&gt;
|-&lt;br /&gt;
| appname || Name of the application || Client-defined || No|| Nielsen Sample App&lt;br /&gt;
|-&lt;br /&gt;
| appversion || Current version of the app used || Client-defined || No || &amp;quot;1.0.2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Nielsen collection facility to which the SDK should connect.&lt;br /&gt;
'''Italian Clients'''&lt;br /&gt;
* &amp;quot;it&amp;quot;&lt;br /&gt;
|| Nielsen-specified || Yes || &amp;quot;it&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || Enables Nielsen console logging. Only required for testing&lt;br /&gt;
|| Nielsen-specified || Optional || &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==== Sample SDK Initialization Code ====&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift  = &lt;br /&gt;
Swift 4.0 Example:&lt;br /&gt;
&amp;lt;code&amp;gt;NielsenInit.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
           &amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
            &amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
            &amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
            &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sample code using AVPlayer.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ViewController.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class ViewController: UIViewController, NielsenAppApiDelegate, AVPictureInPictureControllerDelegate, CLLocationManagerDelegate  {&lt;br /&gt;
    &lt;br /&gt;
    let avPlayerViewController = AVPlayerViewController()&lt;br /&gt;
    var avPlayer:AVPlayer?&lt;br /&gt;
    var nielsenAppApi: NielsenAppApi!&lt;br /&gt;
&lt;br /&gt;
  override func viewDidLoad() {&lt;br /&gt;
        super.viewDidLoad()&lt;br /&gt;
&lt;br /&gt;
self.nielsenAppApi = NielsenInit.createNielsenAppApi(delegate: self)&lt;br /&gt;
NSLog(&amp;quot;Nielsen SDK initialized&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Objective C = &lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;    &lt;br /&gt;
#import &amp;quot;NlsAppApiFactory.h&amp;quot;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@implementation NlsAppApiFactory&lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
{&lt;br /&gt;
    NSDictionary *appInformation = @{&lt;br /&gt;
                                     @&amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot;&lt;br /&gt;
                                     };&lt;br /&gt;
    return [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&lt;br /&gt;
}&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following would be the &amp;lt;code&amp;gt;NlsAppApiFactory.h&amp;lt;/code&amp;gt; file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@class NielsenAppApi;&lt;br /&gt;
@protocol NielsenAppApiDeligate;&lt;br /&gt;
&lt;br /&gt;
@interface NlsAppApiFactory : NSObject &lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppAPI *) createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appversion&amp;quot;, &amp;quot;1.0&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;DEBUG&amp;quot;); // only for debug builds&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&amp;lt;br /&amp;gt;&lt;br /&gt;
* Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== APP SDK Error &amp;amp; Event Codes ==&lt;br /&gt;
To view the Error and Event codes for iOS and Android, please review the [[APP SDK Event Codes|App SDK Event Code]] Reference page.&lt;br /&gt;
== Configure Payload ==&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift = &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
       let channelInfo = [&lt;br /&gt;
            &amp;quot;channelName&amp;quot;: &amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
        &lt;br /&gt;
        let contentMetadata = [&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
                &amp;quot;assetid&amp;quot;: &amp;quot;88675545&amp;quot;,&lt;br /&gt;
                &amp;quot;title&amp;quot;: &amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
                &amp;quot;isfullepisode&amp;quot;:&amp;quot;n&amp;quot;,&lt;br /&gt;
                &amp;quot;adloadtype&amp;quot;:&amp;quot;2&amp;quot;,&lt;br /&gt;
                &amp;quot;program&amp;quot;:&amp;quot;Program Name&amp;quot;,&lt;br /&gt;
                &amp;quot;length&amp;quot;:&amp;quot;3600&amp;quot;, &lt;br /&gt;
                &amp;quot;airdate&amp;quot;:&amp;quot;20171020 10:05:00&amp;quot;&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;     &lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt; &lt;br /&gt;
NSDictionary  *channelInfo = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;channelName&amp;quot;:@&amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
NSDictionary *contentMetadata = @&lt;br /&gt;
  {@&amp;quot;type&amp;quot;: @&amp;quot;content&amp;quot;,&lt;br /&gt;
  @&amp;quot;assetid&amp;quot;: [NSString stringWithFormat:@&amp;quot;ProgramAssetId-%d&amp;quot;, i],&lt;br /&gt;
  @&amp;quot;length&amp;quot;: @&amp;quot;3600&amp;quot;,&lt;br /&gt;
  @&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;title&amp;quot;: @&amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
  @&amp;quot;isfullepisode&amp;quot;: @&amp;quot;y&amp;quot;,&lt;br /&gt;
  @&amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
  @&amp;quot;airdate&amp;quot;: &amp;quot;20161013 20:00:00&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject channelInfo = new JSONObject()&lt;br /&gt;
    .put(&amp;quot;channelname&amp;quot;,&amp;quot;My Channel Name 1&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
JSONObject contentMetadata = new JSONObject()&lt;br /&gt;
//SDK Metadata&lt;br /&gt;
    .put(&amp;quot;type&amp;quot;, &amp;quot;content&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;assetid&amp;quot;, &amp;quot;vid345-67483&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;title&amp;quot;, &amp;quot;Program S3, EP1&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;length&amp;quot;, &amp;quot;3600&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;isfullepisode&amp;quot;, &amp;quot;y&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;adloadtype&amp;quot;, &amp;quot;2&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;airdate&amp;quot;, &amp;quot;20161013 20:00:00&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;   &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Configure metadata === &lt;br /&gt;
Configure metadata should remain constant throughout the completion of an episode or live stream.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| channelName	|| Any string representing the channel/stream	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Content metadata ===&lt;br /&gt;
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| program ||name of program (25 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| title ||name of program (40 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || Yes&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || Yes&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches TV ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || Yes&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
The ad metadata (if applicable) should be passed for each individual ad, if ads are available during or before the stream begins.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Configure API Calls ==&lt;br /&gt;
=== Sample API Sequence ===&lt;br /&gt;
A Sample API sequence could follow this flow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
|On App Start||&amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadata];&amp;lt;/code&amp;gt; || // contentMetadata Object contains the JSON metadata for the impression&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;[nielsenMeter play: channelName];&amp;lt;/code&amp;gt; || // channelName contains JSON metadata of channel/video name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadataObject];&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;[nielsenMeter end];&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
=== Life cycle of SDK instance ===&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[DCR_Video_APP_SDK#play|play]] and [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[DCR_Video_APP_SDK#stop|stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[DCR_Video_APP_SDK#end|end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## &amp;lt;code&amp;gt;appDisableApi&amp;lt;/code&amp;gt; is called&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (assign) BOOL appDisableApi;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] and  [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence of Calls ===&lt;br /&gt;
=== play ===&lt;br /&gt;
Use [[DCR_Video_APP_SDK#play|play]] to pass the channel descriptor information through channelName parameter when the user taps the '''Play''' button on the player.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;   [nielsenAppApi play:(JSONObject channelInfo)];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;    public void play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;nielsenAppApi?.play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void)loadMetadata:(id)contentMetadata;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void loadMetadata(JSONObject contentMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.loadMetadata(contentMetadata)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== playheadPosition ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void) playheadPosition: (long long) playheadPos&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Sending playheadposition for content ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
AVPlayer *player;&lt;br /&gt;
CMTime curTime=[player currentTime];&lt;br /&gt;
int pos = CMTimeGetSeconds(curTime);&lt;br /&gt;
[nAppApiObject playheadPosition:pos];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
        //Monitor the Playhead position of the AVPlayer&lt;br /&gt;
        let timeInterval: CMTime = CMTimeMakeWithSeconds(1.0,10)&lt;br /&gt;
        self.avPlayerViewController.player?.addPeriodicTimeObserver(forInterval: timeInterval, queue: DispatchQueue.main) {(elapsedTime: CMTime) -&amp;gt; Void in&lt;br /&gt;
            if self.avPlayerViewController.player!.currentItem?.status == .readyToPlay {&lt;br /&gt;
                let time : Float64 = self.avPlayerViewController.player!.currentTime().seconds;&lt;br /&gt;
                let pos = Int64(time);&lt;br /&gt;
                NSLog(&amp;quot;New Elapse Time = \(time)&amp;quot;);&lt;br /&gt;
                self.nielsenAppApi?.playheadPosition(pos);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void setPlayheadPosition(long position)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== stop ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void) stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== end ===&lt;br /&gt;
When content stop is initiated and content cannot be resumed from the same position (it can only be restarted from the beginning of stream).&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;- (void) end;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Privacy and Opt-Out ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
&lt;br /&gt;
iOS| &lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL for the Nielsen Privacy web page should be retrieved from the optOutURL property of the SDK object &amp;lt;code&amp;gt;optOutURL&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL in the optOutURL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- === Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = nAppApiObject.optOutURL;&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy App.png|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
[[File:Privacy policy App.png|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Android = &lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking &amp;lt;code&amp;gt;userOptOutURLString()&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public String userOptOutURLString()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the &amp;lt;code&amp;gt; getOptOutStatus() &amp;lt;/code&amp;gt; method.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean getOptOutStatus()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make one update to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;iOS Example:&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
            &amp;quot;appid&amp;quot;: &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Android Example:&amp;lt;/big&amp;gt;''' &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=File:Privacy_policy_App.png&amp;diff=2463</id>
		<title>File:Privacy policy App.png</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=File:Privacy_policy_App.png&amp;diff=2463"/>
		<updated>2018-02-15T15:01:16Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Privacy Policy German&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2462</id>
		<title>DCR Italy Video App SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2462"/>
		<updated>2018-02-15T10:19:45Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: removed play after resume&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK:''' The Nielsen SDK package contains a variety of sample players for your reference.&lt;br /&gt;
If you do not have any of these prerequisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] guide for information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
==  Implementation ==&lt;br /&gt;
This guide covers implementation steps for iOS using Xcode and Android using Android Studio.&lt;br /&gt;
&lt;br /&gt;
== Setting up your  Development Environment  ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
xCode|&lt;br /&gt;
&amp;lt;big&amp;gt;&lt;br /&gt;
'''Configuring Xcode Development Environment''' &lt;br /&gt;
&amp;lt;/big&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 9.0 and above.&lt;br /&gt;
&lt;br /&gt;
The SDK uses the NSURLSession instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': All communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Importing Frameworks'''&amp;lt;/big&amp;gt;&lt;br /&gt;
The first step is to ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Swift'''&amp;lt;/big&amp;gt;&lt;br /&gt;
To import a set of Objective-C files in the same app target as your Swift code, you rely on an Objective-C bridging header to expose those files to Swift. Xcode offers to create this header file when you add a Swift file to an existing Objective-C app, or an Objective-C file to an existing Swift app.&lt;br /&gt;
&lt;br /&gt;
Select File/New File/Objective-C File  &amp;lt;br /&amp;gt;&lt;br /&gt;
Xcode will prompt you to create a bridging header.&lt;br /&gt;
[[File:bridgingheader 2x.png|600px|center|link=]] &amp;lt;br /&amp;gt;&lt;br /&gt;
Once this file has been created, you need to add the following:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Objective-C'''&amp;lt;/big&amp;gt;&lt;br /&gt;
Add the code &lt;br /&gt;
&amp;lt;syntaxhighlight lang =&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 to the View Controller’s header file.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
|Android =&lt;br /&gt;
&amp;lt;big&amp;gt;'''Configuring Android Development Environment'''&amp;lt;/big&amp;gt;'&lt;br /&gt;
*The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package.&lt;br /&gt;
&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Library'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Classes/package&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== SDK Initialization ==&lt;br /&gt;
The latest version of the Nielsen App SDK allows instantiating multiple instances of the SDK object, which can be used simultaneously without any issue. The sharedInstance API that creates a singleton object was deprecated prior to version 5.1.1. (Version 4.0 for Android)&lt;br /&gt;
&lt;br /&gt;
* A maximum of four SDK instances per appid are supported. When a fifth SDK instance is launched, the SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
* When four SDK instances exist, you must destroy an old instance before creating a new one.&lt;br /&gt;
&lt;br /&gt;
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.&lt;br /&gt;
&lt;br /&gt;
* The appid is provided by the Nielsen Technical Account Manager (TAM). The appid is a GUID data type and is specific to the application.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter / Argument !! Description !! Source !! Required? !! Example&lt;br /&gt;
|-&lt;br /&gt;
| appid || Unique id for the application assigned by Nielsen. It is GUID data type.|| Nielsen-specified || Yes || PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&lt;br /&gt;
|-&lt;br /&gt;
| appname || Name of the application || Client-defined || No|| Nielsen Sample App&lt;br /&gt;
|-&lt;br /&gt;
| appversion || Current version of the app used || Client-defined || No || &amp;quot;1.0.2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Nielsen collection facility to which the SDK should connect.&lt;br /&gt;
'''Italian Clients'''&lt;br /&gt;
* &amp;quot;it&amp;quot;&lt;br /&gt;
|| Nielsen-specified || Yes || &amp;quot;it&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || Enables Nielsen console logging. Only required for testing&lt;br /&gt;
|| Nielsen-specified || Optional || &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==== Sample SDK Initialization Code ====&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift  = &lt;br /&gt;
Swift 4.0 Example:&lt;br /&gt;
&amp;lt;code&amp;gt;NielsenInit.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
           &amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
            &amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
            &amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
            &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sample code using AVPlayer.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ViewController.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class ViewController: UIViewController, NielsenAppApiDelegate, AVPictureInPictureControllerDelegate, CLLocationManagerDelegate  {&lt;br /&gt;
    &lt;br /&gt;
    let avPlayerViewController = AVPlayerViewController()&lt;br /&gt;
    var avPlayer:AVPlayer?&lt;br /&gt;
    var nielsenAppApi: NielsenAppApi!&lt;br /&gt;
&lt;br /&gt;
  override func viewDidLoad() {&lt;br /&gt;
        super.viewDidLoad()&lt;br /&gt;
&lt;br /&gt;
self.nielsenAppApi = NielsenInit.createNielsenAppApi(delegate: self)&lt;br /&gt;
NSLog(&amp;quot;Nielsen SDK initialized&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Objective C = &lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;    &lt;br /&gt;
#import &amp;quot;NlsAppApiFactory.h&amp;quot;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@implementation NlsAppApiFactory&lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
{&lt;br /&gt;
    NSDictionary *appInformation = @{&lt;br /&gt;
                                     @&amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot;&lt;br /&gt;
                                     };&lt;br /&gt;
    return [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&lt;br /&gt;
}&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following would be the &amp;lt;code&amp;gt;NlsAppApiFactory.h&amp;lt;/code&amp;gt; file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@class NielsenAppApi;&lt;br /&gt;
@protocol NielsenAppApiDeligate;&lt;br /&gt;
&lt;br /&gt;
@interface NlsAppApiFactory : NSObject &lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppAPI *) createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appversion&amp;quot;, &amp;quot;1.0&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;DEBUG&amp;quot;); // only for debug builds&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&amp;lt;br /&amp;gt;&lt;br /&gt;
* Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== APP SDK Error &amp;amp; Event Codes ==&lt;br /&gt;
To view the Error and Event codes for iOS and Android, please review the [[APP SDK Event Codes|App SDK Event Code]] Reference page.&lt;br /&gt;
== Configure Payload ==&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift = &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
       let channelInfo = [&lt;br /&gt;
            &amp;quot;channelName&amp;quot;: &amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
        &lt;br /&gt;
        let contentMetadata = [&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
                &amp;quot;assetid&amp;quot;: &amp;quot;88675545&amp;quot;,&lt;br /&gt;
                &amp;quot;title&amp;quot;: &amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
                &amp;quot;isfullepisode&amp;quot;:&amp;quot;n&amp;quot;,&lt;br /&gt;
                &amp;quot;adloadtype&amp;quot;:&amp;quot;2&amp;quot;,&lt;br /&gt;
                &amp;quot;program&amp;quot;:&amp;quot;Program Name&amp;quot;,&lt;br /&gt;
                &amp;quot;length&amp;quot;:&amp;quot;3600&amp;quot;, &lt;br /&gt;
                &amp;quot;airdate&amp;quot;:&amp;quot;20171020 10:05:00&amp;quot;&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;     &lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt; &lt;br /&gt;
NSDictionary  *channelInfo = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;channelName&amp;quot;:@&amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
NSDictionary *contentMetadata = @&lt;br /&gt;
  {@&amp;quot;type&amp;quot;: @&amp;quot;content&amp;quot;,&lt;br /&gt;
  @&amp;quot;assetid&amp;quot;: [NSString stringWithFormat:@&amp;quot;ProgramAssetId-%d&amp;quot;, i],&lt;br /&gt;
  @&amp;quot;length&amp;quot;: @&amp;quot;3600&amp;quot;,&lt;br /&gt;
  @&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;title&amp;quot;: @&amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
  @&amp;quot;isfullepisode&amp;quot;: @&amp;quot;y&amp;quot;,&lt;br /&gt;
  @&amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
  @&amp;quot;airdate&amp;quot;: &amp;quot;20161013 20:00:00&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject channelInfo = new JSONObject()&lt;br /&gt;
    .put(&amp;quot;channelname&amp;quot;,&amp;quot;My Channel Name 1&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
JSONObject contentMetadata = new JSONObject()&lt;br /&gt;
//SDK Metadata&lt;br /&gt;
    .put(&amp;quot;type&amp;quot;, &amp;quot;content&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;assetid&amp;quot;, &amp;quot;vid345-67483&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;title&amp;quot;, &amp;quot;Program S3, EP1&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;length&amp;quot;, &amp;quot;3600&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;isfullepisode&amp;quot;, &amp;quot;y&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;adloadtype&amp;quot;, &amp;quot;2&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;airdate&amp;quot;, &amp;quot;20161013 20:00:00&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;   &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Configure metadata === &lt;br /&gt;
Configure metadata should remain constant throughout the completion of an episode or live stream.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| channelName	|| Any string representing the channel/stream	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Content metadata ===&lt;br /&gt;
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| program ||name of program (25 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| title ||name of program (40 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || Yes&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || Yes&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches TV ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || Yes&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
The ad metadata (if applicable) should be passed for each individual ad, if ads are available during or before the stream begins.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Configure API Calls ==&lt;br /&gt;
=== Sample API Sequence ===&lt;br /&gt;
A Sample API sequence could follow this flow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
|On App Start||&amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadata];&amp;lt;/code&amp;gt; || // contentMetadata Object contains the JSON metadata for the impression&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;[nielsenMeter play: channelName];&amp;lt;/code&amp;gt; || // channelName contains JSON metadata of channel/video name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadataObject];&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;[nielsenMeter end];&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
=== Life cycle of SDK instance ===&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[DCR_Video_APP_SDK#play|play]] and [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[DCR_Video_APP_SDK#stop|stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[DCR_Video_APP_SDK#end|end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## &amp;lt;code&amp;gt;appDisableApi&amp;lt;/code&amp;gt; is called&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (assign) BOOL appDisableApi;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] and  [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence of Calls ===&lt;br /&gt;
=== play ===&lt;br /&gt;
Use [[DCR_Video_APP_SDK#play|play]] to pass the channel descriptor information through channelName parameter when the user taps the '''Play''' button on the player.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;   [nielsenAppApi play:(JSONObject channelInfo)];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;    public void play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;nielsenAppApi?.play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void)loadMetadata:(id)contentMetadata;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void loadMetadata(JSONObject contentMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.loadMetadata(contentMetadata)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== playheadPosition ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void) playheadPosition: (long long) playheadPos&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Sending playheadposition for content ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
AVPlayer *player;&lt;br /&gt;
CMTime curTime=[player currentTime];&lt;br /&gt;
int pos = CMTimeGetSeconds(curTime);&lt;br /&gt;
[nAppApiObject playheadPosition:pos];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
        //Monitor the Playhead position of the AVPlayer&lt;br /&gt;
        let timeInterval: CMTime = CMTimeMakeWithSeconds(1.0,10)&lt;br /&gt;
        self.avPlayerViewController.player?.addPeriodicTimeObserver(forInterval: timeInterval, queue: DispatchQueue.main) {(elapsedTime: CMTime) -&amp;gt; Void in&lt;br /&gt;
            if self.avPlayerViewController.player!.currentItem?.status == .readyToPlay {&lt;br /&gt;
                let time : Float64 = self.avPlayerViewController.player!.currentTime().seconds;&lt;br /&gt;
                let pos = Int64(time);&lt;br /&gt;
                NSLog(&amp;quot;New Elapse Time = \(time)&amp;quot;);&lt;br /&gt;
                self.nielsenAppApi?.playheadPosition(pos);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void setPlayheadPosition(long position)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== stop ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void) stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== end ===&lt;br /&gt;
When content stop is initiated and content cannot be resumed from the same position (it can only be restarted from the beginning of stream).&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;- (void) end;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Privacy and Opt-Out ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
&lt;br /&gt;
iOS| &lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL for the Nielsen Privacy web page should be retrieved from the optOutURL property of the SDK object &amp;lt;code&amp;gt;optOutURL&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL in the optOutURL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- === Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = nAppApiObject.optOutURL;&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Android = &lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking &amp;lt;code&amp;gt;userOptOutURLString()&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public String userOptOutURLString()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the &amp;lt;code&amp;gt; getOptOutStatus() &amp;lt;/code&amp;gt; method.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean getOptOutStatus()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make one update to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;iOS Example:&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
            &amp;quot;appid&amp;quot;: &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Android Example:&amp;lt;/big&amp;gt;''' &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Static_Google_AMP_Cloud_API&amp;diff=2439</id>
		<title>DCR Italy Static Google AMP Cloud API</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Static_Google_AMP_Cloud_API&amp;diff=2439"/>
		<updated>2018-01-30T13:20:53Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show you how to enable Digital Content Ratings (DCR) Static measurement on Google AMP.&lt;br /&gt;
&lt;br /&gt;
== Import AMP Analytics Javascript Library ==&lt;br /&gt;
If you have not already, you will need to import the AMP JS library in the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; of your webpage in order to make an AMP page:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script async src=&amp;quot;https://cdn.ampproject.org/v0.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Next, please ensure that the following line is included in the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; of the webpage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script async custom-element=&amp;quot;amp-analytics&amp;quot; src=&amp;quot;https://cdn.ampproject.org/v0/amp-analytics-0.1.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': AMP pages require all traffic to be using HTTPS, including the webpage itself&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Specify the Analytics Provider ==&lt;br /&gt;
DCR measurement can be added to your AMP pages through the AMP-Analytics element:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;amp-analytics type=&amp;quot;nielsen&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Add Nielsen DCR Tags here --&amp;gt;&lt;br /&gt;
&amp;lt;/amp-analytics&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information on the Analytics type, you can refer to the [https://www.ampproject.org/docs/guides/analytics/analytics-vendors Analytics vendors] section of Google's AMP Developer Documentation.&lt;br /&gt;
&lt;br /&gt;
== Configure Metadata ==&lt;br /&gt;
You will need to match the metadata fields on your AMP page with those of your non-AMP page.&lt;br /&gt;
&lt;br /&gt;
=== Metadata Keys ===&lt;br /&gt;
The Nielsen reserved keys are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Example Value !! Required&lt;br /&gt;
|-&lt;br /&gt;
| apid || unique ID assigned by Nielsen || &amp;lt;code&amp;gt;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| prefix || URL prefix to allow EU data collection || &amp;lt;code&amp;gt;eu-&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| apv || current version of the Nielsen implementation || &amp;lt;code&amp;gt;1.0&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| apn || name of the website || &amp;lt;code&amp;gt;My AMP Website&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| section || section of the site to be measured || &amp;lt;code&amp;gt;Entertainment&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| segA || custom segment to be used to break out reporting || &amp;lt;code&amp;gt;Music&amp;lt;/code&amp;gt; ||&lt;br /&gt;
|-&lt;br /&gt;
| segB || custom segment to be used to break out reporting || &amp;lt;code&amp;gt;News&amp;lt;/code&amp;gt; ||&lt;br /&gt;
|-&lt;br /&gt;
| segC || Reserved custom segment for Google AMP || &amp;lt;code&amp;gt;Google AMP&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The values passed through the Nielsen keys will determine the breakouts you will see in reporting. If you decide not to use custom segments A and B, then you do not need to pass a value in these keys. It is suggested you use the same segments used in non-AMP pages.&lt;br /&gt;
&lt;br /&gt;
=== Metadata for Reporting ===&lt;br /&gt;
You can reference the table to determine how the metadata you pass is used to define your reporting structure:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Reporting Level !! Key !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Brand/Sub-brand || apid || brand and sub-brand are determined by assigned App ID passed during initialization&lt;br /&gt;
|-&lt;br /&gt;
| Section || section || section or category for the AMP page&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment A || segA || available segment for custom reporting. Custom segments will roll into the sub-brand&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment B || segB || available segment for custom reporting. Custom segments will roll into the sub-brand&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment C || segC || Custom segment C is reserved for reporting ‘Google AMP’. The Google AMP custom segment will be available under sub-brand and will include the total metrics for all your AMP pages&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you would like your AMP pages to report into the same reporting structure as your website, we recommend passing the same dynamic metadata in Section, Custom Segment A, and Custom Segment B as you are on your website. This way your AMP pageviews contribute to those aggregations.&lt;br /&gt;
&lt;br /&gt;
=== Aggregation Limits ===&lt;br /&gt;
There are limits on the number of unique values that can be aggregated on in reporting. The specific limitations by key are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Aggregation Limit&lt;br /&gt;
|-&lt;br /&gt;
| section || maximum of 25 unique values (section &amp;lt;= 25)&lt;br /&gt;
|-&lt;br /&gt;
| segA || total sum of segA, segB, and segC must be a maximum of 24 unique values (segA + segB + segC &amp;lt;= 24)&lt;br /&gt;
|-&lt;br /&gt;
| segB || total sum of segA, segB, and segC must be a maximum of 24 unique values (segA + segB + segC &amp;lt;= 24)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Example Implementation ==&lt;br /&gt;
The below is an example implementation of Nielsen measurement on an AMP page:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;amp-analytics type=&amp;quot;nielsen&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;application/json&amp;quot;&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;vars&amp;quot;: {&lt;br /&gt;
        &amp;quot;apid&amp;quot;: &amp;quot;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
        &amp;quot;prefix&amp;quot;: &amp;quot;eu-&amp;quot;,&lt;br /&gt;
        &amp;quot;apv&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
        &amp;quot;apn&amp;quot;: &amp;quot;My AMP Website&amp;quot;,&lt;br /&gt;
        &amp;quot;section&amp;quot;: &amp;quot;Entertainment&amp;quot;,&lt;br /&gt;
        &amp;quot;segA&amp;quot;: &amp;quot;Music&amp;quot;,&lt;br /&gt;
        &amp;quot;segB&amp;quot;: &amp;quot;News&amp;quot;,&lt;br /&gt;
        &amp;quot;segC&amp;quot;: &amp;quot;Google AMP&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/amp-analytics&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can find more information about dynamic variables on [https://github.com/ampproject/amphtml/blob/master/spec/amp-var-substitutions.md#page-and-content Google's AMP documentation].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': append &amp;lt;code&amp;gt;#development=1&amp;lt;/code&amp;gt; at the end of your URL to see AMP debug logs in the console. This can be helpful when troubleshooting&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Privacy Policy ==&lt;br /&gt;
Nielsen uses cookies for browser measurement. In order to comply with our privacy restrictions, we ask that you make a link to our Digital Privacy Policy available on your site. You can find our privacy policy here: &lt;br /&gt;
https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Static_Google_AMP_Cloud_API&amp;diff=2438</id>
		<title>DCR Italy Static Google AMP Cloud API</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Static_Google_AMP_Cloud_API&amp;diff=2438"/>
		<updated>2018-01-30T13:19:52Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show you how to enable Digital Content Ratings (DCR) Static measurement on Google AMP.&lt;br /&gt;
&lt;br /&gt;
== Import AMP Analytics Javascript Library ==&lt;br /&gt;
If you have not already, you will need to import the AMP JS library in the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; of your webpage in order to make an AMP page:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script async src=&amp;quot;https://cdn.ampproject.org/v0.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Next, please ensure that the following line is included in the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; of the webpage:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script async custom-element=&amp;quot;amp-analytics&amp;quot; src=&amp;quot;https://cdn.ampproject.org/v0/amp-analytics-0.1.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': AMP pages require all traffic to be using HTTPS, including the webpage itself&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Specify the Analytics Provider ==&lt;br /&gt;
DCR measurement can be added to your AMP pages through the AMP-Analytics element:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;amp-analytics type=&amp;quot;nielsen&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;!-- Add Nielsen DCR Tags here --&amp;gt;&lt;br /&gt;
&amp;lt;/amp-analytics&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information on the Analytics type, you can refer to the [https://www.ampproject.org/docs/guides/analytics/analytics-vendors Analytics vendors] section of Google's AMP Developer Documentation.&lt;br /&gt;
&lt;br /&gt;
== Configure Metadata ==&lt;br /&gt;
You will need to match the metadata fields on your AMP page with those of your non-AMP page.&lt;br /&gt;
&lt;br /&gt;
=== Metadata Keys ===&lt;br /&gt;
The Nielsen reserved keys are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Example Value !! Required&lt;br /&gt;
|-&lt;br /&gt;
| apid || unique ID assigned by Nielsen || &amp;lt;code&amp;gt;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| prefix || URL prefix to allow EU data collection || &amp;lt;code&amp;gt;eu-&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| apv || current version of the Nielsen implementation || &amp;lt;code&amp;gt;1.0&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| apn || name of the website || &amp;lt;code&amp;gt;My AMP Website&amp;lt;/code&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| section || section of the site to be measured || &amp;lt;code&amp;gt;Entertainment&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| segA || custom segment to be used to break out reporting || &amp;lt;code&amp;gt;Music&amp;lt;/code&amp;gt; ||&lt;br /&gt;
|-&lt;br /&gt;
| segB || custom segment to be used to break out reporting || &amp;lt;code&amp;gt;News&amp;lt;/code&amp;gt; ||&lt;br /&gt;
|-&lt;br /&gt;
| segC || Reserved custom segment for Google AMP || &amp;lt;code&amp;gt;Google AMP&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The values passed through the Nielsen keys will determine the breakouts you will see in reporting. If you decide not to use custom segments A and B, then you do not need to pass a value in these keys. It is suggested you use the same segments used in non-AMP pages.&lt;br /&gt;
&lt;br /&gt;
=== Metadata for Reporting ===&lt;br /&gt;
You can reference the table to determine how the metadata you pass is used to define your reporting structure:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Reporting Level !! Key !! Description&lt;br /&gt;
|-&lt;br /&gt;
| Brand/Sub-brand || apid || brand and sub-brand are determined by assigned App ID passed during initialization&lt;br /&gt;
|-&lt;br /&gt;
| Section || section || section or category for the AMP page&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment A || segA || available segment for custom reporting. Custom segments will roll into the sub-brand&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment B || segB || available segment for custom reporting. Custom segments will roll into the sub-brand&lt;br /&gt;
|-&lt;br /&gt;
| Custom Segment C || segC || Custom segment C is reserved for reporting ‘Google AMP’. The Google AMP custom segment will be available under sub-brand and will include the total metrics for all your AMP pages&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you would like your AMP pages to report into the same reporting structure as your website, we recommend passing the same dynamic metadata in Section, Custom Segment A, and Custom Segment B as you are on your website. This way your AMP pageviews contribute to those aggregations.&lt;br /&gt;
&lt;br /&gt;
=== Aggregation Limits ===&lt;br /&gt;
There are limits on the number of unique values that can be aggregated on in reporting. The specific limitations by key are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Aggregation Limit&lt;br /&gt;
|-&lt;br /&gt;
| section || maximum of 25 unique values (section &amp;lt;= 25)&lt;br /&gt;
|-&lt;br /&gt;
| segA || total sum of segA, segB, and segC must be a maximum of 24 unique values (segA + segB + segC &amp;lt;= 24)&lt;br /&gt;
|-&lt;br /&gt;
| segB || total sum of segA, segB, and segC must be a maximum of 24 unique values (segA + segB + segC &amp;lt;= 24)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Example Implementation ==&lt;br /&gt;
The below is an example implementation of Nielsen measurement on an AMP page:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;amp-analytics type=&amp;quot;nielsen&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;script type=&amp;quot;application/json&amp;quot;&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;vars&amp;quot;: {&lt;br /&gt;
        &amp;quot;apid&amp;quot;: &amp;quot;XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
        &amp;quot;prefix&amp;quot;: &amp;quot;eu-&amp;quot;,&lt;br /&gt;
        &amp;quot;apv&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
        &amp;quot;apn&amp;quot;: &amp;quot;My AMP Website&amp;quot;,&lt;br /&gt;
        &amp;quot;section&amp;quot;: &amp;quot;Entertainment&amp;quot;,&lt;br /&gt;
        &amp;quot;segA&amp;quot;: &amp;quot;Music&amp;quot;,&lt;br /&gt;
        &amp;quot;segB&amp;quot;: &amp;quot;News&amp;quot;,&lt;br /&gt;
        &amp;quot;segC&amp;quot;: &amp;quot;Google AMP&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/amp-analytics&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can find more information about dynamic variables on [https://github.com/ampproject/amphtml/blob/master/spec/amp-var-substitutions.md#page-and-content Google's AMP documentation].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': append &amp;lt;code&amp;gt;#development=1&amp;lt;/code&amp;gt; at the end of your URL to see AMP debug logs in the console. This can be helpful when troubleshooting&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Privacy Policy ==&lt;br /&gt;
Nielsen uses cookies for browser measurement. In order to comply with our privacy restrictions, we ask that you make a link to our Digital Privacy Policy available on your site. You can find our privacy policy here: &lt;br /&gt;
http://www.nielsen.com/digitalprivacy#choice&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=International&amp;diff=2331</id>
		<title>International</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=International&amp;diff=2331"/>
		<updated>2017-12-27T10:09:14Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: renamed german browser page title&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
{{CategoryIcon|International.png|International}}&lt;br /&gt;
&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Please contact your Nielsen representative for documentation if the guides for your country aren't listed.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; | Downloads&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;width: 90px;&amp;quot; |{{SmallIcon|DownloadIcon.png|alt=Cloud API}} &lt;br /&gt;
|style=&amp;quot;width: 90px;&amp;quot; | {{SmallIcon|SDKIcon.png}}&lt;br /&gt;
| '''[[Digital Downloads|SDK Downloads]]'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; | Germany&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; |&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | &lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | OS&lt;br /&gt;
!| Guide&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;6&amp;quot; | {{SmallIcon|DEFlagIcon.png}}&lt;br /&gt;
| rowspan=&amp;quot;6&amp;quot; | {{SmallIcon|SDKIcon.png}}&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | {{OSIcon|VideoIcon.png}}&lt;br /&gt;
| {{OSIcon|macOSIcon.png}}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{OSIcon|AndroidIcon.png}}&lt;br /&gt;
| '''[[DCR Germany Video App SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
| {{OSIcon|BrowserIcon.png}}&lt;br /&gt;
| '''[[DCR Germany Video Browser SDK]]'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; | Italy&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; |&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | &lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | OS&lt;br /&gt;
!| Guide&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;6&amp;quot; | {{SmallIcon|ITFlagIcon.png}}&lt;br /&gt;
| rowspan=&amp;quot;6&amp;quot; | {{SmallIcon|SDKIcon.png}}&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | {{OSIcon|VideoIcon.png}}&lt;br /&gt;
| {{OSIcon|macOSIcon.png}}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{OSIcon|AndroidIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Video App SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | {{OSIcon|BrowserIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Video Browser SDK (6.0.0)]]'''&lt;br /&gt;
|-&lt;br /&gt;
| '''[[DCR Italy Video Browser SDK (6.0.1)]] Object Video only'''&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | {{OSIcon|StaticIcon.png}}&lt;br /&gt;
| {{OSIcon|macOSIcon.png}}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{OSIcon|AndroidIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Static App SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
| {{OSIcon|BrowserIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Static Browser SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
|  {{OSIcon|FacebookIcon.png|alt=Facebook Instant Articles}}&lt;br /&gt;
| '''[[DCR Italy Static Facebook Instant Articles Browser SDK]]'''&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2326</id>
		<title>DCR Italy Video Browser SDK (6.0.0)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2326"/>
		<updated>2017-12-27T09:58:11Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: /* SDK Event Lifecycle */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID is needed. The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration from Nielsen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  apid: &amp;quot;XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot; // eg. PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
*Add Static Queue Snippet&lt;br /&gt;
*Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
===Create SDK Instance===&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization API call:&lt;br /&gt;
&lt;br /&gt;
==== Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,{nol_sdkDebug: &amp;quot;debug&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following  values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter	!! Description	!! Required !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid	&lt;br /&gt;
|| Unique ID assigned to player/site. &lt;br /&gt;
*Test: begins with ‘T’ and is used for testing &lt;br /&gt;
*Production: begins with ‘P’ and is used in live environment when testing and certification is completed&lt;br /&gt;
||Yes||'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&lt;br /&gt;
|-&lt;br /&gt;
|instanceName ||	Name of SDK instance ||Yes	 ||	&amp;quot;any string value&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug	|| Enables Nielsen console logging. Only required for testing	||Optional	|| nol_sdkDebug: &amp;quot;debug&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;apid&amp;gt;.js, will be downloaded based on the apid and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK600.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
==== Example SDK Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
*content: identify video&lt;br /&gt;
*ad: identify each ad&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type ||	Type of asset	|| &amp;quot;content&amp;quot;	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid	|| Unique ID assigned to content (max. 40 characters) || custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| program	|| Name of program (25 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| title	|| Episode title (40 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| length	|| Length of content in seconds for VOD (Video on demand). The value for live stream content is 86400 ||&lt;br /&gt;
*&amp;quot;seconds&amp;quot;– VOD&lt;br /&gt;
*&amp;quot;86400&amp;quot;– Live Stream&lt;br /&gt;
||	&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate	|| The airdate in the linear TV. Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; ||	YYYYMMDD hh:mm:ss	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode	|| Full episode flag ||	&lt;br /&gt;
*&amp;quot;y&amp;quot;– full episode&lt;br /&gt;
*&amp;quot;n&amp;quot;– non full episode	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
|adloadtype	|| type of ad load:&lt;br /&gt;
* 1) Linear – matches TV ad load &lt;br /&gt;
* 2) Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;1&amp;quot; – content with linear ads &lt;br /&gt;
*&amp;quot;2&amp;quot; – content with dynamic ads	&lt;br /&gt;
||&lt;br /&gt;
✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Example Content Object =====&lt;br /&gt;
&lt;br /&gt;
'''Note:''' all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           'content',&lt;br /&gt;
  assetid:        'VID123-123456',&lt;br /&gt;
  program:        'program name',&lt;br /&gt;
  title:          'episode title',&lt;br /&gt;
  length:         '1020',    // length in seconds (String)&lt;br /&gt;
  airdate:        '19700101 00:00:00',&lt;br /&gt;
  isfullepisode:  'y',&lt;br /&gt;
  adloadtype:     '2'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad, if ads are available during or before the stream (content) begins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example Ad Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create pre-roll ad object&lt;br /&gt;
var prerollMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: 'AD-1',&lt;br /&gt;
  type:    'preroll'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is ggPM().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
nSdkInstance.ggPM('event', parameter);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event name !! Values to pass !!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 'loadMetadata'	|| content/ad metadata object	|| Needs to be called at the beginning of each content/ad metadata object&lt;br /&gt;
|-&lt;br /&gt;
| 'setPlayheadPosition'&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;VOD (or ad ): || current position in seconds (integer) &amp;lt;br/&amp;gt;&lt;br /&gt;
*&amp;quot;Live: current UTC timestamp (seconds since January 1st 1970)&amp;lt;br/&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
Pass playhead position every second during playback&lt;br /&gt;
|-&lt;br /&gt;
| 'stop' ||	playhead position in seconds	|| Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| 'end'	|| playhead position in seconds	|| This event has to be called once for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Playhead position as integer&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' has to be called every second&lt;br /&gt;
&lt;br /&gt;
==== Example Events ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass ( Object ):''' Content Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', contentMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass  ( Object ):''' Pre-roll AD Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', prerollMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' setPlayheadPosition  |  '''Value Pass ( Integer ):''' playheadPosition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' stop  |  '''Value Pass ( Integer ):''' stopPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('stop', stopPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' end  |  '''Value Pass ( Integer ):''' endPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('end', endPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Interrupt Scenarios ==&lt;br /&gt;
&lt;br /&gt;
=== Pause Event ===&lt;br /&gt;
The setPlayheadPostion event is used for handling pause. To indicate pause, stop passing the playhead position to the SDK. Once the content resumes, begin sending the playhead again with the correct playhead value.&lt;br /&gt;
&lt;br /&gt;
=== Other Interrupt Scenarios ===&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function closePlayer() {&lt;br /&gt;
	if (inMidroll) {    // Only inside a midroll indicate &amp;lt;stop&amp;gt; for the ad&lt;br /&gt;
		nSdkInstance.ggPM('stop', playheadPositionMidroll);&lt;br /&gt;
	}&lt;br /&gt;
	nSdkInstance.ggPM('end', playheadPositionContent);    // Indicate &amp;lt;end&amp;gt; for the content&lt;br /&gt;
};&lt;br /&gt;
window.addEventListener( ('onpagehide' in window) ? &amp;quot;pagehide&amp;quot; : &amp;quot;beforeunload&amp;quot;, function (e) {	// for iOS mobile &amp;quot;pagehide&amp;quot; recommended by apple&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==  SDK Event Lifecycle ==&lt;br /&gt;
&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
'''Note''' &lt;br /&gt;
*For Audiweb there is no need to tag ads in video stream ... please see 1st example how to use without ads!&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle without ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:even browser no ads.png]]&lt;br /&gt;
&lt;br /&gt;
==== Example without ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);  // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle with ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:event browser.png|event browser.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example with ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// PREROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end pre-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);&lt;br /&gt;
&lt;br /&gt;
// MIDROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
  &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end mid-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); &lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// POSTROLL&lt;br /&gt;
nSdkInstance.ggPM('loadmetadata', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); // end post-roll stream&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling 'stop', 'end', or 'loadmetadata'.&lt;br /&gt;
&lt;br /&gt;
'''Note :''' For Ad, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' For pre-roll ads you have to call the loadMetadata event for content at the start of stream and after the preroll&lt;br /&gt;
&lt;br /&gt;
== Nielsen Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
====Opt Back In====&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'debug'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
&lt;br /&gt;
====Example Production Initialization Call ====&lt;br /&gt;
Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;, &amp;quot;myPlayerName&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=2189</id>
		<title>DCR Italy Video Browser SDK (6.0.1)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=2189"/>
		<updated>2017-11-30T15:03:43Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show how to integrate the Nielsen Software Development Kit (SDK) to enable Digital Content Ratings (DCR) video measurement on browser players.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID, clientid and vcid is needed. These values are provided by Nielsen.&lt;br /&gt;
&lt;br /&gt;
The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
AppID: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The clientid is your 'parent# or companyid'&lt;br /&gt;
clientid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;XX-XXXXXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The vcid is your channel id&lt;br /&gt;
vcid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&amp;quot;xXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
* Add Static Queue Snippet&lt;br /&gt;
* Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
=== Create SDK Instance ===&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
       clientid: &amp;quot;XX-XXXXXX&amp;quot;,  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
       vcid: &amp;quot;cXX&amp;quot;,            // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
       nol_sdkDebug: &amp;quot;debug&amp;quot;   // should be deleted when going live&lt;br /&gt;
    }&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following five values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site || &amp;lt;code&amp;gt;&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || &amp;lt;code&amp;gt;&amp;quot;any string value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value has to be passed in 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value has to be passed 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Nielsen console logging. Only required for testing. in 3rd parameter object || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK601.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;, nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
* content: identify video&lt;br /&gt;
* ad: identify each ad ('''for Italy there is no need to tag ads''')&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*video – &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to content (max. 40 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || &amp;lt;code&amp;gt;YYYYMMDD hh:mm:ss&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; - full episode&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt; - non-full episode&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load &amp;quot;1&amp;quot;&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI) &amp;quot;2&amp;quot;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| ✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| subbrand || subbrand/VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || Nielsen provided || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Content Object'''&lt;br /&gt;
... with all mandatory parameters - you may ignore the optional ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           &amp;quot;content&amp;quot;,&lt;br /&gt;
  assetid:        &amp;quot;VID123-123456&amp;quot;,&lt;br /&gt;
  program:        &amp;quot;program name&amp;quot;,&lt;br /&gt;
  title:          &amp;quot;episode title&amp;quot;,&lt;br /&gt;
  length:         &amp;quot;1020&amp;quot;,&lt;br /&gt;
  airdate:        &amp;quot;19700101 00:00:00&amp;quot;,&lt;br /&gt;
  isfullepisode:  &amp;quot;y&amp;quot;,&lt;br /&gt;
  adloadtype:     &amp;quot;2&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
=== Ad Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Audiweb there is no need to tag ads in video stream ... you may ignore this paragraph. If there are ads in your stream, but not tagged than simply do nothing while ad is playing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of ad || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || uniqueID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Ad Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;//create ad object&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: &amp;quot;AD-1&amp;quot;,&lt;br /&gt;
  type:    &amp;quot;preroll&amp;quot;&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''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.&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is &amp;lt;code&amp;gt;ggPM()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM('event', parameter, ...);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Number !! Values to pass !! Event Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'3'&amp;lt;/code&amp;gt; || content/ad metadata object || load content metadata || Load metadata event for content. Has to be called at the very first beginning of each stream.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'5'&amp;lt;/code&amp;gt; || playhead position || content play || Call when content or ads start playing or resumes from pause. &lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'6'&amp;lt;/code&amp;gt; || playhead position || pause || Call when content or ads is pausing. Use Event 5 to resume ...&lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt; || playhead position || stop || Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'8'&amp;lt;/code&amp;gt; || playhead position from, playhead position to || seek || Call when scrubbing forward or backward with playhead position 'from' and 'to'&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt; || content/ad metadata object || load ad metadata || Call at the beginning of each ad, don’t use ‘play’ (event 5) if event 15 is used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; || playhead position || playhead position || '''VOD''': current position in seconds. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
Note: has to be called on a secondly basis.&lt;br /&gt;
For each ad the playheads starts with 0 (no Live unix timestamp for ads)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt; || playhead position || end || This event has to be called '''once''' for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Event Lifecycle ===&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;example '''without''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': if there are ads played in stream simply use a pause (event 6) when ads start playing and a play (event 5) when content start playing.&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&amp;lt;big&amp;gt; example '''with''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// Preroll&lt;br /&gt;
nSdkInstance.ggPM('15', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Midroll&lt;br /&gt;
nSdkInstance.ggPM('15', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// Postroll&lt;br /&gt;
nSdkInstance.ggPM('15', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Italy there is no need to tag ads in video stream ... ignore &amp;quot;with ads&amp;quot; example!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': Event &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling event &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when buffering occurs you have to send a event 6 (pause) and after buffering finished a 5 (play).&lt;br /&gt;
&lt;br /&gt;
'''Note''': For Ad Pods, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note''': When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Pause'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; is used for handling pause. To indicate pause, stop passing the playhead position to the SDK and send Event 6 with playhead once. When content resumes, begin sending the playhead again with the correct playhead value. Also if buffering occurs for more than 1 second you may use Event 6 (pause) to indicate that.&lt;br /&gt;
e.g. pause at 1m2s and resume after a couple of seconds:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // now send nothing to SDK until player resumes (automatically because of buffering ends or user unpauses/resumes play&lt;br /&gt;
nSdkInstance.ggPM('5', 62); // ONLY WHEN PLAYING CONTENT (not ads!) - play/5 when resume occurs (when user click play or buffering ends)&lt;br /&gt;
nSdkInstance.ggPM('49', 63);&lt;br /&gt;
nSdkInstance.ggPM('49', 64);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Seek'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; is used for handling forward/backward seek. To indicate seek, send Event 8 with 'from' and 'to' playhead.&lt;br /&gt;
e.g. seek from 1m2s to 2m0s:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // use pause, because buffering will occur (to be on safe side)&lt;br /&gt;
nSdkInstance.ggPM('8', 62,120);&lt;br /&gt;
nSdkInstance.ggPM('5', 120); // ONLY WHEN PLAYING CONTENT (not ads!) - play/5 when resuming&lt;br /&gt;
nSdkInstance.ggPM('49', 120);&lt;br /&gt;
nSdkInstance.ggPM('49', 121);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Interruption Scenarios'''&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function closePlayer() {&lt;br /&gt;
  if (insideMidroll) {   // Only inside a midroll indicate 'stop' for the ad&lt;br /&gt;
    nSdkInstance.ggPM('7', playheadPositionMidroll);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // Indicate 'end' for the content and 'stop' for the stream&lt;br /&gt;
  nSdkInstance.ggPM('57', playheadPositionContent);&lt;br /&gt;
  nSdkInstance.ggPM('7', playheadPositionContent);&lt;br /&gt;
};&lt;br /&gt;
if ('onpagehide' in window) {&lt;br /&gt;
	window.addEventListener(&amp;quot;pagehide&amp;quot;, function (e) {	// for iOS mobile recommended by apple&lt;br /&gt;
		closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
	});&lt;br /&gt;
} else {&lt;br /&gt;
	window.addEventListener(&amp;quot;beforeunload&amp;quot;, function (e) {&lt;br /&gt;
		closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
	});&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2101</id>
		<title>DCR Italy Video App SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_App_SDK&amp;diff=2101"/>
		<updated>2017-11-21T13:56:00Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To start using the App SDK, the following details are required:&lt;br /&gt;
* '''App ID (appid):''' Unique ID assigned to the player/site and configured by product.&lt;br /&gt;
* '''sfcode:''' Unique identifier for the environment that the SDK should point to.&lt;br /&gt;
* '''Nielsen SDK:''' The Nielsen SDK package contains a variety of sample players for your reference.&lt;br /&gt;
If you do not have any of these prerequisites or if you have any questions, please contact our SDK sales support team.&lt;br /&gt;
Refer to [[Digital Measurement Onboarding]] guide for information on how to get a Nielsen App SDK and appid.&lt;br /&gt;
&lt;br /&gt;
==  Implementation ==&lt;br /&gt;
This guide covers implementation steps for iOS using Xcode and Android using Android Studio.&lt;br /&gt;
&lt;br /&gt;
== Setting up your  Development Environment  ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
xCode|&lt;br /&gt;
&amp;lt;big&amp;gt;&lt;br /&gt;
'''Configuring Xcode Development Environment''' &lt;br /&gt;
&amp;lt;/big&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK is compatible with Apple iOS versions 9.0 and above.&lt;br /&gt;
&lt;br /&gt;
The SDK uses the NSURLSession instead of the deprecated NSURLConnection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': All communications between the SDK and the Census (Collection Facility) use HTTPS.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Importing Frameworks'''&amp;lt;/big&amp;gt;&lt;br /&gt;
The first step is to ensure that the following frameworks and libraries are imported into the Frameworks folder of the Xcode project before creating an instance of the Nielsen App SDK object.&lt;br /&gt;
* UIKit.framework&lt;br /&gt;
* Foundation.framework&lt;br /&gt;
* AdSupport.framework&lt;br /&gt;
* SystemConfiguration.framework&lt;br /&gt;
* Security.framework&lt;br /&gt;
** Nielsen Analytics framework makes use of a number of functions in this library.&lt;br /&gt;
* AVFoundation.framework&lt;br /&gt;
** This framework is mandatory for the iOS SDK version 5.1.1 to work.&lt;br /&gt;
* CoreLocation.framework (Not applicable for International (Germany))&lt;br /&gt;
* CoreMedia.framework&lt;br /&gt;
* NielsenAppApi.framework&lt;br /&gt;
* libc++.tbd (as SDK contains Objective C++ source file)&lt;br /&gt;
** Alternatively, include -lstdc++ in Build Settings → Other Linker Flag of the Xcode project&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Example'''&lt;br /&gt;
* Extract “NielsenAppApi.Framework” from the Nielsen App SDK sample app and copy it to Frameworks folder of the Xcode project.&lt;br /&gt;
* Add the code &amp;lt;code&amp;gt;-#import NielsenAppApi/NielsenAppApi.h&amp;lt;/code&amp;gt; to the View Controller’s header file.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Ensure that the following are included in the Linked Frameworks and Libraries list (located in the project’s Summary settings).&lt;br /&gt;
* Nielsen App SDK&lt;br /&gt;
* iOS security framework&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Swift'''&amp;lt;/big&amp;gt;&lt;br /&gt;
To import a set of Objective-C files in the same app target as your Swift code, you rely on an Objective-C bridging header to expose those files to Swift. Xcode offers to create this header file when you add a Swift file to an existing Objective-C app, or an Objective-C file to an existing Swift app.&lt;br /&gt;
&lt;br /&gt;
Select File/New File/Objective-C File  &amp;lt;br /&amp;gt;&lt;br /&gt;
Xcode will prompt you to create a bridging header.&lt;br /&gt;
[[File:bridgingheader 2x.png|600px|center|link=]] &amp;lt;br /&amp;gt;&lt;br /&gt;
Once this file has been created, you need to add the following:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Using Objective-C'''&amp;lt;/big&amp;gt;&lt;br /&gt;
Add the code &lt;br /&gt;
&amp;lt;syntaxhighlight lang =&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 to the View Controller’s header file.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
|Android =&lt;br /&gt;
&amp;lt;big&amp;gt;'''Configuring Android Development Environment'''&amp;lt;/big&amp;gt;'&lt;br /&gt;
*The Nielsen App SDK (located in the ''com.nielsen.app.sdk'' package) class is the primary application interface to the Nielsen App SDK on Android.&lt;br /&gt;
*The Nielsen App SDK class is defined as the only public class belonging to the com.nielsen.app.sdk package.&lt;br /&gt;
&lt;br /&gt;
'''Nielsen App SDK is compatible with Android OS versions 2.3+. Clients can control / configure the protocol to be used – HTTPS or HTTP to suit their needs.'''&lt;br /&gt;
&lt;br /&gt;
The Nielsen App SDK 1.2 library is composed of two parts:&lt;br /&gt;
* The Java AppSdk.jar library that runs on the Android’s Dalvik Virtual Machine.&lt;br /&gt;
* The C/C++ libAppSdk.so native library that runs directly on the device’s hardware.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': App SDK 4.0.0 contains AppSDK.jar component only and does not support C/C++ libAppSdk.so components.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The requirement for the Java ''AppSdk.jar'' library and the ''libAppSdk.so'' native library will depend on the type of host application that will make use of them.&lt;br /&gt;
* '''For Video player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should use a media player supporting HLS streaming (Android 3.0 and later will support it natively).&lt;br /&gt;
** If the player application uses a 3rd party media player implementing its own HLS, then the minimum Android version will be limited to version 2.3, since the SDK depends on Google Play support to work properly.&lt;br /&gt;
* '''For Audio player applications'''&lt;br /&gt;
** The Android OS hosting the App SDK should be at version 2.3 and later since the SDK depends on the Google Play support to work properly.&lt;br /&gt;
Ensure to unzip the Nielsen App SDK sample app and copy the ''AppSdk.jar'' into the libs/ folder on the App’s Eclipse project. Copy the ''libAppSdk.so'' file under ''libs/armeabi/'' folder into the same Eclipse project.&lt;br /&gt;
* App SDK 1.2 provides support for x86, mips, and armeabi-7a architecture; the respective ''libAppSdk.so'' can be found under the ''libs/x86/'', ''libs/mips/'', and ''libs/armeabi-7a/'' folders.&lt;br /&gt;
Add the following permissions on the project’s ''AndroidManifest.xml'' file.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_COARSE_LOCATION&amp;quot; android:required=&amp;quot;false&amp;quot; /&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.ACCESS_NETWORK_STATE&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.INTERNET&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more details to handle runtime permissions in Android versions, please visit [https://developer.android.com/training/permissions/requesting.html].   Download the latest ''google-play-services_lib'' and include it in the App’s project in order to use the App SDK.&lt;br /&gt;
* App SDK checks to see if there is a Google service available and updated.&lt;br /&gt;
* If not available or updated, App SDK will not use this service when executing its functions and will make reference to missing imports and the app will not be compiled.&lt;br /&gt;
To include the Google Play library in the media player project, copy the ''google-play-services_lib'' folder into the same location as the project&lt;br /&gt;
* Access '''File &amp;gt; Import'''.&lt;br /&gt;
* Select '''Existing Android Code into Workspace''' and click '''Next'''.&lt;br /&gt;
* Click '''Browse''' and navigate to the ''google-play-services_lib'' to include it into the projects.&lt;br /&gt;
* Select the exact '''Project Build Target''' for Eclipse to use from Android SDK.&lt;br /&gt;
** Android 4.4.2, etc. OR&lt;br /&gt;
** Edit ''project.properties'' file to point to Android target version e.g. target= android-19.&lt;br /&gt;
Once the google-play-services_lib is included into the App project, include the following code under the &amp;lt;code&amp;gt;&amp;lt;application&amp;gt;&amp;lt;/code&amp;gt; node in the &amp;lt;code&amp;gt;AndroidManifest.xml&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&amp;lt;meta-data android:name=&amp;quot;com.google.android.gms.version&amp;quot; android:value=&amp;quot;@integer/google_play_services_version&amp;quot;/&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also, include the ''version.xml'' file that comes with the ''google-play-services_lib'' under the res/values directory of the media player project.&lt;br /&gt;
* Once the files are in place, import com.nielsen.app.sdk to the java source code and start accessing the public interface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Library'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nielsen App SDK uses the following packages/classes from the Google Play service.&lt;br /&gt;
* google-play-services_lib&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Classes/package&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient;&lt;br /&gt;
* com.google.android.gms.ads.identifier.AdvertisingIdClient.Info;&lt;br /&gt;
* com.google.android.gms.common.ConnectionResult;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesUtil;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesRepairableException;&lt;br /&gt;
* com.google.android.gms.common.GooglePlayServicesNotAvailableException;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== SDK Initialization ==&lt;br /&gt;
The latest version of the Nielsen App SDK allows instantiating multiple instances of the SDK object, which can be used simultaneously without any issue. The sharedInstance API that creates a singleton object was deprecated prior to version 5.1.1. (Version 4.0 for Android)&lt;br /&gt;
&lt;br /&gt;
* A maximum of four SDK instances per appid are supported. When a fifth SDK instance is launched, the SDK will return “nil” from [[initWithAppInfo:delegate:]]&lt;br /&gt;
* When four SDK instances exist, you must destroy an old instance before creating a new one.&lt;br /&gt;
&lt;br /&gt;
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.&lt;br /&gt;
&lt;br /&gt;
* The appid is provided by the Nielsen Technical Account Manager (TAM). The appid is a GUID data type and is specific to the application.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter / Argument !! Description !! Source !! Required? !! Example&lt;br /&gt;
|-&lt;br /&gt;
| appid || Unique id for the application assigned by Nielsen. It is GUID data type.|| Nielsen-specified || Yes || PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&lt;br /&gt;
|-&lt;br /&gt;
| appname || Name of the application || Client-defined || No|| Nielsen Sample App&lt;br /&gt;
|-&lt;br /&gt;
| appversion || Current version of the app used || Client-defined || No || &amp;quot;1.0.2&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| sfcode || Nielsen collection facility to which the SDK should connect.&lt;br /&gt;
'''Italian Clients'''&lt;br /&gt;
* &amp;quot;it&amp;quot;&lt;br /&gt;
|| Nielsen-specified || Yes || &amp;quot;it&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_devDebug || Enables Nielsen console logging. Only required for testing&lt;br /&gt;
|| Nielsen-specified || Optional || &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
==== Sample SDK Initialization Code ====&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift  = &lt;br /&gt;
Swift 4.0 Example:&lt;br /&gt;
&amp;lt;code&amp;gt;NielsenInit.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
           &amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
            &amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
            &amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
            &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sample code using AVPlayer.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ViewController.swift&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class ViewController: UIViewController, NielsenAppApiDelegate, AVPictureInPictureControllerDelegate, CLLocationManagerDelegate  {&lt;br /&gt;
    &lt;br /&gt;
    let avPlayerViewController = AVPlayerViewController()&lt;br /&gt;
    var avPlayer:AVPlayer?&lt;br /&gt;
    var nielsenAppApi: NielsenAppApi!&lt;br /&gt;
&lt;br /&gt;
  override func viewDidLoad() {&lt;br /&gt;
        super.viewDidLoad()&lt;br /&gt;
&lt;br /&gt;
self.nielsenAppApi = NielsenInit.createNielsenAppApi(delegate: self)&lt;br /&gt;
NSLog(&amp;quot;Nielsen SDK initialized&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Objective C = &lt;br /&gt;
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;    &lt;br /&gt;
#import &amp;quot;NlsAppApiFactory.h&amp;quot;&lt;br /&gt;
#import &amp;lt;NielsenAppApi/NielsenAppApi.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@implementation NlsAppApiFactory&lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
{&lt;br /&gt;
    NSDictionary *appInformation = @{&lt;br /&gt;
                                     @&amp;quot;appid&amp;quot;: &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appversion&amp;quot;: &amp;quot;1.0&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;appname&amp;quot;: &amp;quot;app name here&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;,&lt;br /&gt;
                                     @&amp;quot;nol_devDebug&amp;quot;: @&amp;quot;DEBUG&amp;quot;&lt;br /&gt;
                                     };&lt;br /&gt;
    return [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];&lt;br /&gt;
}&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The following would be the &amp;lt;code&amp;gt;NlsAppApiFactory.h&amp;lt;/code&amp;gt; file:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
#import &amp;lt;Foundation/Foundation.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
@class NielsenAppApi;&lt;br /&gt;
@protocol NielsenAppApiDeligate;&lt;br /&gt;
&lt;br /&gt;
@interface NlsAppApiFactory : NSObject &lt;br /&gt;
&lt;br /&gt;
+ (NielsenAppAPI *) createNielsenAppApiWithDelegate:(id&amp;lt;NielsenAppApiDelegate&amp;gt;)delegate;&lt;br /&gt;
&lt;br /&gt;
@end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &lt;br /&gt;
&lt;br /&gt;
[[AppSDK()]] is no longer a singleton object and should be initialized as below.&lt;br /&gt;
&lt;br /&gt;
'''Initialization of App SDK object through a JSON object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appversion&amp;quot;, &amp;quot;1.0&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;appname&amp;quot;, &amp;quot;Sample App Name&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;nol_devDebug&amp;quot;, &amp;quot;DEBUG&amp;quot;); // only for debug builds&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Here, &amp;lt;code&amp;gt;appContext&amp;lt;/code&amp;gt; is the App context object and &amp;lt;code&amp;gt;appSdkConfig&amp;lt;/code&amp;gt; is JSON object for holding the parameters (&amp;lt;code&amp;gt;appid&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;appname&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sfcode&amp;lt;/code&amp;gt;) the App passes to the Nielsen App SDK via a JSON string. The appid is obtained from Nielsen operational support and is unique to the app.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The integration of Nielsen App SDK will depend on type of client app.&amp;lt;br /&amp;gt;&lt;br /&gt;
* Ensure that SDK files (AppSdk.jar and libAppSdk.so [App SDK 1.2 Only]) are included under the App’s project and the App SDK is linked to the App (the setting to link App SDK to the App can be found on property page of the App’s project).&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== APP SDK Error &amp;amp; Event Codes ==&lt;br /&gt;
To view the Error and Event codes for iOS and Android, please review the [[APP SDK Event Codes|App SDK Event Code]] Reference page.&lt;br /&gt;
== Configure Payload ==&lt;br /&gt;
=== Handling JSON Metadata ===&lt;br /&gt;
All the SDK methods handles only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.&lt;br /&gt;
* NSDictionary object&lt;br /&gt;
** If an object of unexpected type is passed to the method, the error message will be logged.&lt;br /&gt;
** If string has invalid JSON format, the error message will be logged.&lt;br /&gt;
* JSON value must be string value.&lt;br /&gt;
** This includes boolean and numeric values. For example, a value of true should be represented with &amp;quot;true&amp;quot;, number value 123 should be &amp;quot;123&amp;quot;.&lt;br /&gt;
** All the Variable Names like appid, appname, sfcode, dataSrc, title, type etc. are case-sensitive. Use the correct variable name as specified in the documentation.&lt;br /&gt;
* JSON string can be prepared using either raw NSString or serialized NSDictionary.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift = &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
       let channelInfo = [&lt;br /&gt;
            &amp;quot;channelName&amp;quot;: &amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
];&lt;br /&gt;
        &lt;br /&gt;
        let contentMetadata = [&lt;br /&gt;
                &amp;quot;type&amp;quot;: &amp;quot;content&amp;quot;,&lt;br /&gt;
                &amp;quot;assetid&amp;quot;: &amp;quot;88675545&amp;quot;,&lt;br /&gt;
                &amp;quot;title&amp;quot;: &amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
                &amp;quot;isfullepisode&amp;quot;:&amp;quot;n&amp;quot;,&lt;br /&gt;
                &amp;quot;adloadtype&amp;quot;:&amp;quot;2&amp;quot;,&lt;br /&gt;
                &amp;quot;program&amp;quot;:&amp;quot;Program Name&amp;quot;,&lt;br /&gt;
                &amp;quot;length&amp;quot;:&amp;quot;3600&amp;quot;, &lt;br /&gt;
                &amp;quot;airdate&amp;quot;:&amp;quot;20171020 10:05:00&amp;quot;&lt;br /&gt;
];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;     &lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt; &lt;br /&gt;
NSDictionary  *channelInfo = @&lt;br /&gt;
{&lt;br /&gt;
  @&amp;quot;channelName&amp;quot;:@&amp;quot;My Channel Name 1&amp;quot;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
NSDictionary *contentMetadata = @&lt;br /&gt;
  {@&amp;quot;type&amp;quot;: @&amp;quot;content&amp;quot;,&lt;br /&gt;
  @&amp;quot;assetid&amp;quot;: [NSString stringWithFormat:@&amp;quot;ProgramAssetId-%d&amp;quot;, i],&lt;br /&gt;
  @&amp;quot;length&amp;quot;: @&amp;quot;3600&amp;quot;,&lt;br /&gt;
  @&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;,&lt;br /&gt;
  @&amp;quot;title&amp;quot;: @&amp;quot;Program S3, EP1&amp;quot;,&lt;br /&gt;
  @&amp;quot;isfullepisode&amp;quot;: @&amp;quot;y&amp;quot;,&lt;br /&gt;
  @&amp;quot;adloadtype&amp;quot;: &amp;quot;2&amp;quot;,&lt;br /&gt;
  @&amp;quot;airdate&amp;quot;: &amp;quot;20161013 20:00:00&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
JSONObject channelInfo = new JSONObject()&lt;br /&gt;
    .put(&amp;quot;channelname&amp;quot;,&amp;quot;My Channel Name 1&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
JSONObject contentMetadata = new JSONObject()&lt;br /&gt;
//SDK Metadata&lt;br /&gt;
    .put(&amp;quot;type&amp;quot;, &amp;quot;content&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;assetid&amp;quot;, &amp;quot;vid345-67483&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;program&amp;quot;, &amp;quot;Program Name&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;title&amp;quot;, &amp;quot;Program S3, EP1&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;length&amp;quot;, &amp;quot;3600&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;isfullepisode&amp;quot;, &amp;quot;y&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;adloadtype&amp;quot;, &amp;quot;2&amp;quot;)&lt;br /&gt;
    .put(&amp;quot;airdate&amp;quot;, &amp;quot;20161013 20:00:00&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;   &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Configure metadata === &lt;br /&gt;
Configure metadata should remain constant throughout the completion of an episode or live stream.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| channelName	|| Any string representing the channel/stream	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Content metadata ===&lt;br /&gt;
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of asset || &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || unique ID assigned to asset || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| program ||name of program (25 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| title ||name of program (40 character limit) || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| length || length of content in seconds || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || Yes&lt;br /&gt;
|-&lt;br /&gt;
| airdate || the airdate in the linear TV || YYYYMMDD HH24:MI:SS || Yes&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || full episode flag || &amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt;- full episode, &amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt;- non full episode || Yes&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype || type of ad load:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; Linear – matches TV ad load&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - DCR measures content with dynamic ads || Yes&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata ===&lt;br /&gt;
The ad metadata (if applicable) should be passed for each individual ad, if ads are available during or before the stream begins.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Configure API Calls ==&lt;br /&gt;
=== Sample API Sequence ===&lt;br /&gt;
A Sample API sequence could follow this flow:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Type !! Sample code !! Description&lt;br /&gt;
|-&lt;br /&gt;
|On App Start||&amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadata];&amp;lt;/code&amp;gt; || // contentMetadata Object contains the JSON metadata for the impression&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | Start of stream || &amp;lt;code&amp;gt;[nielsenMeter play: channelName];&amp;lt;/code&amp;gt; || // channelName contains JSON metadata of channel/video name being played&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;[nielsenMeter loadMetadata: contentMetadataObject];&amp;lt;/code&amp;gt; || // contentMetadataObject contains the JSON metadata for the content being played&lt;br /&gt;
|-&lt;br /&gt;
| Content || &amp;lt;code&amp;gt;[nielsenMeter playheadPosition: position];&amp;lt;/code&amp;gt; || // playheadPosition is position of the playhead while the content is being played&lt;br /&gt;
|-&lt;br /&gt;
| End of Stream || &amp;lt;code&amp;gt;[nielsenMeter end];&amp;lt;/code&amp;gt; || // Content playback is completed.&lt;br /&gt;
|}&lt;br /&gt;
=== Life cycle of SDK instance ===&lt;br /&gt;
Life cycle of SDK instance includes four general states:&lt;br /&gt;
# '''Initial state''' – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the '''Initial state'''.&lt;br /&gt;
# '''Idle state''' – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for the play event to occur.&lt;br /&gt;
# '''Processing state''' – The SDK instance is processing playing information. [[DCR_Video_APP_SDK#play|play]] and [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.&lt;br /&gt;
## [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]] – Call this API every one second when playhead position timer is fired.&lt;br /&gt;
## [[DCR_Video_APP_SDK#stop|stop]] – Call this API when the playback is paused, switches between content and ad (within the same content playback) or encounters interruptions.&lt;br /&gt;
## [[DCR_Video_APP_SDK#end|end]] – SDK instance exits from Processing state when this API is called.&lt;br /&gt;
# '''Disabled state''' – The SDK instance is disabled and is not processing playing information. SDK instance moves into this state in one of the following scenarios.&lt;br /&gt;
## Initialization fails&lt;br /&gt;
## &amp;lt;code&amp;gt;appDisableApi&amp;lt;/code&amp;gt; is called&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (assign) BOOL appDisableApi;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&lt;br /&gt;
&lt;br /&gt;
'''Note''': In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call [[stop]] to stop the measurement.&lt;br /&gt;
* As soon as the playback resumes, call [[DCR_Video_APP_SDK#play|play]], [[DCR_Video_APP_SDK#loadMetadata|loadMetadata]] and  [[DCR_Video_APP_SDK#playheadPosition|playheadPosition]].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sequence of Calls ===&lt;br /&gt;
=== play ===&lt;br /&gt;
Use [[DCR_Video_APP_SDK#play|play]] to pass the channel descriptor information through channelName parameter when the user taps the '''Play''' button on the player.&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;   [nielsenAppApi play:(JSONObject channelInfo)];&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;    public void play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;nielsenAppApi?.play(JSONObject channelInfo);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== loadMetadata ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void)loadMetadata:(id)contentMetadata;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void loadMetadata(JSONObject contentMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.loadMetadata(contentMetadata)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== playheadPosition ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
– (void) playheadPosition: (long long) playheadPos&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Sending playheadposition for content ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
AVPlayer *player;&lt;br /&gt;
CMTime curTime=[player currentTime];&lt;br /&gt;
int pos = CMTimeGetSeconds(curTime);&lt;br /&gt;
[nAppApiObject playheadPosition:pos];&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
        //Monitor the Playhead position of the AVPlayer&lt;br /&gt;
        let timeInterval: CMTime = CMTimeMakeWithSeconds(1.0,10)&lt;br /&gt;
        self.avPlayerViewController.player?.addPeriodicTimeObserver(forInterval: timeInterval, queue: DispatchQueue.main) {(elapsedTime: CMTime) -&amp;gt; Void in&lt;br /&gt;
            if self.avPlayerViewController.player!.currentItem?.status == .readyToPlay {&lt;br /&gt;
                let time : Float64 = self.avPlayerViewController.player!.currentTime().seconds;&lt;br /&gt;
                let pos = Int64(time);&lt;br /&gt;
                NSLog(&amp;quot;New Elapse Time = \(time)&amp;quot;);&lt;br /&gt;
                self.nielsenAppApi?.playheadPosition(pos);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void setPlayheadPosition(long position)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== stop ===&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;– (void) stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== end ===&lt;br /&gt;
When content stop is initiated and content cannot be resumed from the same position (it can only be restarted from the beginning of stream).&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;- (void) end;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;public void stop()&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;self.nielsenAppApi?.stop&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Privacy and Opt-Out ==&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
&lt;br /&gt;
iOS| &lt;br /&gt;
== iOS Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL for the Nielsen Privacy web page should be retrieved from the optOutURL property of the SDK object &amp;lt;code&amp;gt;optOutURL&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL in the optOutURL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the [[optOutStatus]] method.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- === Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;NielsenAppApi nAppApiObject;&lt;br /&gt;
@property(strong) UIWebView *optOutView;&lt;br /&gt;
&lt;br /&gt;
// create WebView and set self as delegate&lt;br /&gt;
self.optOutView=[[UIWebViewalloc]initWithFrame:self.view.bounds];&lt;br /&gt;
&lt;br /&gt;
self.optOutView.scalesPageToFit = yes;&lt;br /&gt;
// get Nielsen defined web address and load the page&lt;br /&gt;
NSString *webAddress = nAppApiObject.optOutURL;&lt;br /&gt;
&lt;br /&gt;
if(webAddress == nil)&lt;br /&gt;
    { // Handle it gracefully and retry later}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
    [optOutView loadRequest:[NSURLRequest requestWithURL:webAddress]];&lt;br /&gt;
    // show the view to the user&lt;br /&gt;
    [self.view addSubview:optOutView];&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
*URL to this web page should be called from SDK and opened in 'WebView' / External browser.&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle this case and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status, use the [[optOutStatus]] property from Nielsen's SDK API.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt;&lt;br /&gt;
@property (readonly) BOOL optOutStatus;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*App should provide a UI control like 'close' or 'back' button to close the 'WebView' / External browser.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Users can opt out or opt back into Nielsen Measurement. Opt-Out feature relies on iOS' system setting – &amp;quot;Limit Ad Tracking&amp;quot;. The setting can be accessed in the Settings application on any iOS device: '''Settings → Privacy → Advertising → Limit Ad Tracking'''.&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen online measurement research when the &amp;quot;Limit Ad Tracking&amp;quot; setting is enabled.&lt;br /&gt;
&lt;br /&gt;
[[File:Opt-Out iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Android = &lt;br /&gt;
== Android Opt-Out Implementation ==&lt;br /&gt;
To opt out, users must have access to &amp;quot;[https://priv-policy.imrworldwide.com/priv/mobile/it/it/optout.html About Nielsen Measurement]&amp;quot; page. User can click this page from app settings screen.&lt;br /&gt;
&lt;br /&gt;
Include '''About Nielsen Measurement and Your Choices''' link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
*URL to this web page should be called from SDK by invoking &amp;lt;code&amp;gt;userOptOutURLString()&amp;lt;/code&amp;gt; and opened in 'WebView' / External browser.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public String userOptOutURLString()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.&lt;br /&gt;
*To retrieve the current Opt-Out status of a device, use the &amp;lt;code&amp;gt; getOptOutStatus() &amp;lt;/code&amp;gt; method.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public boolean getOptOutStatus()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Displaying Opt-Out in a WebView ===&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
optOutUrl = mAppSdk.userOptOutURLString();&lt;br /&gt;
if(optOutUrl !=null)&lt;br /&gt;
{&lt;br /&gt;
   mWebView = (WebView) findViewById(R.id.webView);&lt;br /&gt;
   mWebView.getSettings().setJavaScriptEnabled(true);&lt;br /&gt;
   mWebView.getSettings().setBuiltInZoomControls(true);&lt;br /&gt;
   mWebView.getSettings().setDisplayZoomControls(false);&lt;br /&gt;
   mWebView.getSettings().setLoadWithOverviewMode(true);&lt;br /&gt;
   mWebView.getSettings().setUseWideViewPort(true);&lt;br /&gt;
   mWebView.setWebViewClient(new MonitorWebView());&lt;br /&gt;
   mWebView.setWebChromeClient(new WebChromeClient());&lt;br /&gt;
   mWebView.loadUrl(optOutUrl);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
   //Handle it gracefully and Retry later&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The app must provide access to &amp;quot;About Nielsen Measurement&amp;quot; page for the users. Include &amp;quot;About Nielsen Measurement&amp;quot; and Your Choices link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.&lt;br /&gt;
&lt;br /&gt;
[[File:Privacy policy iOS.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' When ‘WebView’ / External browser is closed, do not pass the status returned from ‘WebView’ / External browser to the SDK within the app, as the new Opt-Out page will not return any response.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' App SDK manages the user’s choice (Opt-Out / Opt-In), the app does not need to manage this status.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Starting from SDK version 5.1.1.18:&lt;br /&gt;
*SDK will be sending the data pings to census even though SDK is opted out (In earlier releases all the traffic from SDK to census will be ceased). However, all the outgoing pings will have the parameter uoo=true using which backend can ignore this data.&lt;br /&gt;
*Current Opt-Out page is now updated to have no hyperlinks for Opt-Out / Opt-In operations. SDK Opt-Out has to be done via&lt;br /&gt;
'''Google Settings → Ads → Opt out of Ads Personalization'''.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' For Amazon devices, see [[#Opt-Out Implementation for Amazon Devices|Opt-Out Implementation for Amazon Devices]] below.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:andr-ads.jpg|link=]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' The App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out Implementation for Amazon Devices ==&lt;br /&gt;
Amazon device users can opt out or opt back into Nielsen Measurement, any time using the device’s setting – 'Limit Ad Tracking' (Interest-based ads).&lt;br /&gt;
&lt;br /&gt;
User is opted out of Nielsen Online Measurement when ‘Limit Ad Tracking’ is enabled.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''For devices running on Fire OS 5.1 and above, retrieve the Ad tracking value.'''&lt;br /&gt;
=== Retrieving Ad tracking Value ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
ContentResolver cr = getContentResolver();&lt;br /&gt;
int limitAdTracking = Secure.getInt(cr, &amp;quot;limit_ad_tracking&amp;quot;, 2);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;0&amp;quot; if enabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;1&amp;quot; if disabled&lt;br /&gt;
*Returns limit_ad_tracking value &amp;quot;2&amp;quot; if ad tracking is not supported (below Fire OS 5.1).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' Google Play Services are not needed to retrieve ad tracking state on Amazon devices. Limit Ad Tracking can be accessed through '''Settings → Apps &amp;amp; Games → Advertising ID'''.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make one update to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;iOS Example:&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
            &amp;quot;appid&amp;quot;: &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Android Example:&amp;lt;/big&amp;gt;''' &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2074</id>
		<title>DCR Italy Video Browser SDK (6.0.0)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2074"/>
		<updated>2017-11-16T09:12:44Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID is needed. The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration from Nielsen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  apid: &amp;quot;XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot; // eg. PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
*Add Static Queue Snippet&lt;br /&gt;
*Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
===Create SDK Instance===&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization API call:&lt;br /&gt;
&lt;br /&gt;
==== Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,{nol_sdkDebug: &amp;quot;debug&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following  values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter	!! Description	!! Required !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid	&lt;br /&gt;
|| Unique ID assigned to player/site. &lt;br /&gt;
*Test: begins with ‘T’ and is used for testing &lt;br /&gt;
*Production: begins with ‘P’ and is used in live environment when testing and certification is completed&lt;br /&gt;
||Yes||'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&lt;br /&gt;
|-&lt;br /&gt;
|instanceName ||	Name of SDK instance ||Yes	 ||	&amp;quot;any string value&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug	|| Enables Nielsen console logging. Only required for testing	||Optional	|| nol_sdkDebug: &amp;quot;debug&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;apid&amp;gt;.js, will be downloaded based on the apid and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK600.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
==== Example SDK Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
*content: identify video&lt;br /&gt;
*ad: identify each ad&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type ||	Type of asset	|| &amp;quot;content&amp;quot;	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid	|| Unique ID assigned to content (max. 40 characters) || custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| program	|| Name of program (25 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| title	|| Episode title (40 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| length	|| Length of content in seconds for VOD (Video on demand). The value for live stream content is 86400 ||&lt;br /&gt;
*&amp;quot;seconds&amp;quot;– VOD&lt;br /&gt;
*&amp;quot;86400&amp;quot;– Live Stream&lt;br /&gt;
||	&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate	|| The airdate in the linear TV. Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; ||	YYYYMMDD hh:mm:ss	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode	|| Full episode flag ||	&lt;br /&gt;
*&amp;quot;y&amp;quot;– full episode&lt;br /&gt;
*&amp;quot;n&amp;quot;– non full episode	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
|adloadtype	|| type of ad load:&lt;br /&gt;
* 1) Linear – matches TV ad load &lt;br /&gt;
* 2) Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;1&amp;quot; – content with linear ads &lt;br /&gt;
*&amp;quot;2&amp;quot; – content with dynamic ads	&lt;br /&gt;
||&lt;br /&gt;
✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Example Content Object =====&lt;br /&gt;
&lt;br /&gt;
'''Note:''' all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           'content',&lt;br /&gt;
  assetid:        'VID123-123456',&lt;br /&gt;
  program:        'program name',&lt;br /&gt;
  title:          'episode title',&lt;br /&gt;
  length:         '1020',    // length in seconds (String)&lt;br /&gt;
  airdate:        '19700101 00:00:00',&lt;br /&gt;
  isfullepisode:  'y',&lt;br /&gt;
  adloadtype:     '2'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad, if ads are available during or before the stream (content) begins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example Ad Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create pre-roll ad object&lt;br /&gt;
var prerollMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: 'AD-1',&lt;br /&gt;
  type:    'preroll'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is ggPM().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
nSdkInstance.ggPM('event', parameter);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event name !! Values to pass !!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 'loadMetadata'	|| content/ad metadata object	|| Needs to be called at the beginning of each content/ad metadata object&lt;br /&gt;
|-&lt;br /&gt;
| 'setPlayheadPosition'&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;VOD (or ad ): || current position in seconds (integer) &amp;lt;br/&amp;gt;&lt;br /&gt;
*&amp;quot;Live: current UTC timestamp (seconds since January 1st 1970)&amp;lt;br/&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
Pass playhead position every second during playback&lt;br /&gt;
|-&lt;br /&gt;
| 'stop' ||	playhead position in seconds	|| Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| 'end'	|| playhead position in seconds	|| This event has to be called once for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Playhead position as integer&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' has to be called every second&lt;br /&gt;
&lt;br /&gt;
==== Example Events ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass ( Object ):''' Content Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', contentMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass  ( Object ):''' Pre-roll AD Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', prerollMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' setPlayheadPosition  |  '''Value Pass ( Integer ):''' playheadPosition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' stop  |  '''Value Pass ( Integer ):''' stopPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('stop', stopPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' end  |  '''Value Pass ( Integer ):''' endPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('end', endPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Interrupt Scenarios ==&lt;br /&gt;
&lt;br /&gt;
=== Pause Event ===&lt;br /&gt;
The setPlayheadPostion event is used for handling pause. To indicate pause, stop passing the playhead position to the SDK. Once the content resumes, begin sending the playhead again with the correct playhead value.&lt;br /&gt;
&lt;br /&gt;
=== Other Interrupt Scenarios ===&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function closePlayer() {&lt;br /&gt;
	if (inMidroll) {    // Only inside a midroll indicate &amp;lt;stop&amp;gt; for the ad&lt;br /&gt;
		nSdkInstance.ggPM('stop', playheadPositionMidroll);&lt;br /&gt;
	}&lt;br /&gt;
	nSdkInstance.ggPM('end', playheadPositionContent);    // Indicate &amp;lt;end&amp;gt; for the content&lt;br /&gt;
};&lt;br /&gt;
window.addEventListener( ('onpagehide' in window) ? &amp;quot;pagehide&amp;quot; : &amp;quot;beforeunload&amp;quot;, function (e) {	// for iOS mobile &amp;quot;pagehide&amp;quot; recommended by apple&lt;br /&gt;
	closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===  SDK Event Lifecycle ===&lt;br /&gt;
&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
'''Note''' &lt;br /&gt;
*For Audiweb there is no need to tag ads in video stream ... please see 1st example how to use without ads!&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle without ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:even browser no ads.png]]&lt;br /&gt;
&lt;br /&gt;
==== Example without ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);  // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle with ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:event browser.png|event browser.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example with ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// PREROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end pre-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);&lt;br /&gt;
&lt;br /&gt;
// MIDROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
  &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end mid-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); &lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// POSTROLL&lt;br /&gt;
nSdkInstance.ggPM('loadmetadata', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); // end post-roll stream&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling 'stop', 'end', or 'loadmetadata'.&lt;br /&gt;
&lt;br /&gt;
'''Note :''' For Ad, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' For pre-roll ads you have to call the loadMetadata event for content at the start of stream and after the preroll&lt;br /&gt;
&lt;br /&gt;
== Nielsen Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
====Opt Back In====&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'debug'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
&lt;br /&gt;
====Example Production Initialization Call ====&lt;br /&gt;
Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;, &amp;quot;myPlayerName&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=2073</id>
		<title>DCR Italy Video Browser SDK (6.0.1)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=2073"/>
		<updated>2017-11-15T15:36:30Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show how to integrate the Nielsen Software Development Kit (SDK) to enable Digital Content Ratings (DCR) video measurement on browser players.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID, clientid and vcid is needed. These values are provided by Nielsen.&lt;br /&gt;
&lt;br /&gt;
The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
AppID: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The clientid is your 'parent# or companyid'&lt;br /&gt;
clientid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;XX-XXXXXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The vcid is your channel id&lt;br /&gt;
vcid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&amp;quot;xXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
* Add Static Queue Snippet&lt;br /&gt;
* Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
=== Create SDK Instance ===&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
       clientid: &amp;quot;XX-XXXXXX&amp;quot;,  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
       vcid: &amp;quot;cXX&amp;quot;,            // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
       nol_sdkDebug: &amp;quot;debug&amp;quot;   // should be deleted when going live&lt;br /&gt;
    }&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following five values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site || &amp;lt;code&amp;gt;&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || &amp;lt;code&amp;gt;&amp;quot;any string value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value has to be passed in 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value has to be passed 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Nielsen console logging. Only required for testing. in 3rd parameter object || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK601.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;, nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
* content: identify video&lt;br /&gt;
* ad: identify each ad ('''for Italy there is no need to tag ads''')&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*video – &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to content (max. 40 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || &amp;lt;code&amp;gt;YYYYMMDD hh:mm:ss&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; - full episode&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt; - non-full episode&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load &amp;quot;1&amp;quot;&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI) &amp;quot;2&amp;quot;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| ✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| subbrand || subbrand/VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || Nielsen provided || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Content Object'''&lt;br /&gt;
... with all mandatory parameters - you may ignore the optional ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           &amp;quot;content&amp;quot;,&lt;br /&gt;
  assetid:        &amp;quot;VID123-123456&amp;quot;,&lt;br /&gt;
  program:        &amp;quot;program name&amp;quot;,&lt;br /&gt;
  title:          &amp;quot;episode title&amp;quot;,&lt;br /&gt;
  length:         &amp;quot;1020&amp;quot;,&lt;br /&gt;
  airdate:        &amp;quot;19700101 00:00:00&amp;quot;,&lt;br /&gt;
  isfullepisode:  &amp;quot;y&amp;quot;,&lt;br /&gt;
  adloadtype:     &amp;quot;2&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
=== Ad Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Audiweb there is no need to tag ads in video stream ... you may ignore this paragraph. If there are ads in your stream, but not tagged than simply do nothing while ad is playing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of ad || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || uniqueID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Ad Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;//create ad object&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: &amp;quot;AD-1&amp;quot;,&lt;br /&gt;
  type:    &amp;quot;preroll&amp;quot;&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''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.&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is &amp;lt;code&amp;gt;ggPM()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM('event', parameter, ...);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Number !! Values to pass !! Event Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'3'&amp;lt;/code&amp;gt; || content/ad metadata object || load content metadata || Load metadata event for content. Has to be called at the very first beginning of each stream.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'5'&amp;lt;/code&amp;gt; || playhead position || content play || Call when content or ads start playing or resumes from pause. &lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'6'&amp;lt;/code&amp;gt; || playhead position || pause || Call when content or ads is pausing. Use Event 5 to resume ...&lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt; || playhead position || stop || Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'8'&amp;lt;/code&amp;gt; || playhead position from, playhead position to || seek || Call when scrubbing forward or backward with playhead position 'from' and 'to'&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt; || content/ad metadata object || load ad metadata || Call at the beginning of each ad, don’t use ‘play’ (event 5) if event 15 is used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; || playhead position || playhead position || '''VOD''': current position in seconds. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
Note: has to be called on a secondly basis.&lt;br /&gt;
For each ad the playheads starts with 0 (no Live unix timestamp for ads)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt; || playhead position || end || This event has to be called '''once''' for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Event Lifecycle ===&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;example '''without''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': if there are ads played in stream simply use a pause (event 6) when ads start playing and a play (event 5) when content start playing.&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&amp;lt;big&amp;gt; example '''with''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// Preroll&lt;br /&gt;
nSdkInstance.ggPM('15', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Midroll&lt;br /&gt;
nSdkInstance.ggPM('15', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// Postroll&lt;br /&gt;
nSdkInstance.ggPM('15', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Italy there is no need to tag ads in video stream ... ignore &amp;quot;with ads&amp;quot; example!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': Event &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling event &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when buffering occurs you have to send a event 6 (pause) and after buffering finished a 5 (play).&lt;br /&gt;
&lt;br /&gt;
'''Note''': For Ad Pods, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note''': When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Pause'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; is used for handling pause. To indicate pause, stop passing the playhead position to the SDK and send Event 6 with playhead once. When content resumes, begin sending the playhead again with the correct playhead value. Also if buffering occurs for more than 1 second you may use Event 6 (pause) to indicate that.&lt;br /&gt;
e.g. pause at 1m2s and resume after a couple of seconds:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // now send nothing to SDK until player resumes (automatically because of buffering ends or user unpauses/resumes play&lt;br /&gt;
nSdkInstance.ggPM('5', 62); // play/5 when resume occurs (when user click play or buffering ends)&lt;br /&gt;
nSdkInstance.ggPM('49', 63);&lt;br /&gt;
nSdkInstance.ggPM('49', 64);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Seek'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; is used for handling forward/backward seek. To indicate seek, send Event 8 with 'from' and 'to' playhead.&lt;br /&gt;
e.g. seek from 1m2s to 2m0s:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // use pause, because buffering will occur (to be on safe side)&lt;br /&gt;
nSdkInstance.ggPM('8', 62,120);&lt;br /&gt;
nSdkInstance.ggPM('5', 120); // play/5 when resuming&lt;br /&gt;
nSdkInstance.ggPM('49', 120);&lt;br /&gt;
nSdkInstance.ggPM('49', 121);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Interruption Scenarios'''&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function closePlayer() {&lt;br /&gt;
  if (insideMidroll) {   // Only inside a midroll indicate 'stop' for the ad&lt;br /&gt;
    nSdkInstance.ggPM('7', playheadPositionMidroll);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // Indicate 'end' for the content and 'stop' for the stream&lt;br /&gt;
  nSdkInstance.ggPM('57', playheadPositionContent);&lt;br /&gt;
  nSdkInstance.ggPM('7', playheadPositionContent);&lt;br /&gt;
};&lt;br /&gt;
if ('onpagehide' in window) {&lt;br /&gt;
	window.addEventListener(&amp;quot;pagehide&amp;quot;, function (e) {	// for iOS mobile recommended by apple&lt;br /&gt;
		closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
	});&lt;br /&gt;
} else {&lt;br /&gt;
	window.addEventListener(&amp;quot;beforeunload&amp;quot;, function (e) {&lt;br /&gt;
		closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
	});&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2072</id>
		<title>DCR Italy Video Browser SDK (6.0.0)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2072"/>
		<updated>2017-11-15T15:33:29Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID is needed. The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration from Nielsen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  apid: &amp;quot;XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot; // eg. PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
*Add Static Queue Snippet&lt;br /&gt;
*Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
===Create SDK Instance===&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization API call:&lt;br /&gt;
&lt;br /&gt;
==== Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,{nol_sdkDebug: &amp;quot;debug&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following  values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter	!! Description	!! Required !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid	&lt;br /&gt;
|| Unique ID assigned to player/site. &lt;br /&gt;
*Test: begins with ‘T’ and is used for testing &lt;br /&gt;
*Production: begins with ‘P’ and is used in live environment when testing and certification is completed&lt;br /&gt;
||Yes||'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&lt;br /&gt;
|-&lt;br /&gt;
|instanceName ||	Name of SDK instance ||Yes	 ||	&amp;quot;any string value&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug	|| Enables Nielsen console logging. Only required for testing	||Optional	|| nol_sdkDebug: &amp;quot;debug&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;apid&amp;gt;.js, will be downloaded based on the apid and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK600.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
==== Example SDK Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
*content: identify video&lt;br /&gt;
*ad: identify each ad&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type ||	Type of asset	|| &amp;quot;content&amp;quot;	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid	|| Unique ID assigned to content (max. 40 characters) || custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| program	|| Name of program (25 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| title	|| Episode title (40 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| length	|| Length of content in seconds for VOD (Video on demand). The value for live stream content is 86400 ||&lt;br /&gt;
*&amp;quot;seconds&amp;quot;– VOD&lt;br /&gt;
*&amp;quot;86400&amp;quot;– Live Stream&lt;br /&gt;
||	&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate	|| The airdate in the linear TV. Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; ||	YYYYMMDD hh:mm:ss	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode	|| Full episode flag ||	&lt;br /&gt;
*&amp;quot;y&amp;quot;– full episode&lt;br /&gt;
*&amp;quot;n&amp;quot;– non full episode	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
|adloadtype	|| type of ad load:&lt;br /&gt;
* 1) Linear – matches TV ad load &lt;br /&gt;
* 2) Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;1&amp;quot; – content with linear ads &lt;br /&gt;
*&amp;quot;2&amp;quot; – content with dynamic ads	&lt;br /&gt;
||&lt;br /&gt;
✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Example Content Object =====&lt;br /&gt;
&lt;br /&gt;
'''Note:''' all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           'content',&lt;br /&gt;
  assetid:        'VID123-123456',&lt;br /&gt;
  program:        'program name',&lt;br /&gt;
  title:          'episode title',&lt;br /&gt;
  length:         '1020',    // length in seconds (String)&lt;br /&gt;
  airdate:        '19700101 00:00:00',&lt;br /&gt;
  isfullepisode:  'y',&lt;br /&gt;
  adloadtype:     '2'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad, if ads are available during or before the stream (content) begins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example Ad Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create pre-roll ad object&lt;br /&gt;
var prerollMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: 'AD-1',&lt;br /&gt;
  type:    'preroll'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is ggPM().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
nSdkInstance.ggPM('event', parameter);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event name !! Values to pass !!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 'loadMetadata'	|| content/ad metadata object	|| Needs to be called at the beginning of each content/ad metadata object&lt;br /&gt;
|-&lt;br /&gt;
| 'setPlayheadPosition'&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;VOD (or ad ): || current position in seconds (integer) &amp;lt;br/&amp;gt;&lt;br /&gt;
*&amp;quot;Live: current UTC timestamp (seconds since January 1st 1970)&amp;lt;br/&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
Pass playhead position every second during playback&lt;br /&gt;
|-&lt;br /&gt;
| 'stop' ||	playhead position in seconds	|| Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| 'end'	|| playhead position in seconds	|| This event has to be called once for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Playhead position as integer&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' has to be called every second&lt;br /&gt;
&lt;br /&gt;
==== Example Events ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass ( Object ):''' Content Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', contentMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass  ( Object ):''' Pre-roll AD Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', prerollMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' setPlayheadPosition  |  '''Value Pass ( Integer ):''' playheadPosition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' stop  |  '''Value Pass ( Integer ):''' stopPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('stop', stopPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' end  |  '''Value Pass ( Integer ):''' endPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('end', endPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Interrupt Scenarios ==&lt;br /&gt;
&lt;br /&gt;
=== Pause Event ===&lt;br /&gt;
The setPlayheadPostion event is used for handling pause. To indicate pause, stop passing the playhead position to the SDK. Once the content resumes, begin sending the playhead again with the correct playhead value.&lt;br /&gt;
&lt;br /&gt;
=== Other Interrupt Scenarios ===&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
function closePlayer() {&lt;br /&gt;
  // Only inside a midroll indicate &amp;lt;stop&amp;gt; for the ad&lt;br /&gt;
  if (inMidroll) {nSdkInstance.ggPM('stop', playheadPositionMidroll);}&lt;br /&gt;
  &lt;br /&gt;
  // Indicate &amp;lt;end&amp;gt; for the content&lt;br /&gt;
  nSdkInstance.ggPM('end', playheadPositionContent);&lt;br /&gt;
};&lt;br /&gt;
if ('onpagehide' in window) {&lt;br /&gt;
	window.addEventListener(&amp;quot;pagehide&amp;quot;, function (e) {	// for iOS mobile recommended by apple&lt;br /&gt;
		closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
	});&lt;br /&gt;
} else {&lt;br /&gt;
	window.addEventListener(&amp;quot;beforeunload&amp;quot;, function (e) {&lt;br /&gt;
		closePlayer();   // call nielsensdk with end/stop&lt;br /&gt;
	});&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===  SDK Event Lifecycle ===&lt;br /&gt;
&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
'''Note''' &lt;br /&gt;
*For Audiweb there is no need to tag ads in video stream ... please see 1st example how to use without ads!&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle without ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:even browser no ads.png]]&lt;br /&gt;
&lt;br /&gt;
==== Example without ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);  // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle with ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:event browser.png|event browser.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example with ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// PREROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end pre-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);&lt;br /&gt;
&lt;br /&gt;
// MIDROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
  &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end mid-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); &lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// POSTROLL&lt;br /&gt;
nSdkInstance.ggPM('loadmetadata', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); // end post-roll stream&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling 'stop', 'end', or 'loadmetadata'.&lt;br /&gt;
&lt;br /&gt;
'''Note :''' For Ad, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' For pre-roll ads you have to call the loadMetadata event for content at the start of stream and after the preroll&lt;br /&gt;
&lt;br /&gt;
== Nielsen Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
====Opt Back In====&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'debug'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
&lt;br /&gt;
====Example Production Initialization Call ====&lt;br /&gt;
Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;, &amp;quot;myPlayerName&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2070</id>
		<title>DCR Italy Video Browser SDK (6.0.0)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2070"/>
		<updated>2017-11-15T09:52:04Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID is needed. The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration from Nielsen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  apid: &amp;quot;XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot; // eg. PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
*Add Static Queue Snippet&lt;br /&gt;
*Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
===Create SDK Instance===&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization API call:&lt;br /&gt;
&lt;br /&gt;
==== Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,{nol_sdkDebug: &amp;quot;debug&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following  values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter	!! Description	!! Required !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid	&lt;br /&gt;
|| Unique ID assigned to player/site. &lt;br /&gt;
*Test: begins with ‘T’ and is used for testing &lt;br /&gt;
*Production: begins with ‘P’ and is used in live environment when testing and certification is completed&lt;br /&gt;
||Yes||'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&lt;br /&gt;
|-&lt;br /&gt;
|instanceName ||	Name of SDK instance ||Yes	 ||	&amp;quot;any string value&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug	|| Enables Nielsen console logging. Only required for testing	||Optional	|| nol_sdkDebug: &amp;quot;debug&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;apid&amp;gt;.js, will be downloaded based on the apid and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK600.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
==== Example SDK Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
*content: identify video&lt;br /&gt;
*ad: identify each ad&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type ||	Type of asset	|| &amp;quot;content&amp;quot;	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid	|| Unique ID assigned to content (max. 40 characters) || custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| program	|| Name of program (25 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| title	|| Episode title (40 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| length	|| Length of content in seconds for VOD (Video on demand). The value for live stream content is 86400 ||&lt;br /&gt;
*&amp;quot;seconds&amp;quot;– VOD&lt;br /&gt;
*&amp;quot;86400&amp;quot;– Live Stream&lt;br /&gt;
||	&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate	|| The airdate in the linear TV. Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; ||	YYYYMMDD hh:mm:ss	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode	|| Full episode flag ||	&lt;br /&gt;
*&amp;quot;y&amp;quot;– full episode&lt;br /&gt;
*&amp;quot;n&amp;quot;– non full episode	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
|adloadtype	|| type of ad load:&lt;br /&gt;
* 1) Linear – matches TV ad load &lt;br /&gt;
* 2) Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;1&amp;quot; – content with linear ads &lt;br /&gt;
*&amp;quot;2&amp;quot; – content with dynamic ads	&lt;br /&gt;
||&lt;br /&gt;
✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Example Content Object =====&lt;br /&gt;
&lt;br /&gt;
'''Note:''' all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           'content',&lt;br /&gt;
  assetid:        'VID123-123456',&lt;br /&gt;
  program:        'program name',&lt;br /&gt;
  title:          'episode title',&lt;br /&gt;
  length:         '1020',    // length in seconds (String)&lt;br /&gt;
  airdate:        '19700101 00:00:00',&lt;br /&gt;
  isfullepisode:  'y',&lt;br /&gt;
  adloadtype:     '2'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad, if ads are available during or before the stream (content) begins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example Ad Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create pre-roll ad object&lt;br /&gt;
var prerollMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: 'AD-1',&lt;br /&gt;
  type:    'preroll'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is ggPM().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
nSdkInstance.ggPM('event', parameter);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event name !! Values to pass !!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 'loadMetadata'	|| content/ad metadata object	|| Needs to be called at the beginning of each content/ad metadata object&lt;br /&gt;
|-&lt;br /&gt;
| 'setPlayheadPosition'&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;VOD (or ad ): || current position in seconds (integer) &amp;lt;br/&amp;gt;&lt;br /&gt;
*&amp;quot;Live: current UTC timestamp (seconds since January 1st 1970)&amp;lt;br/&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
Pass playhead position every second during playback&lt;br /&gt;
|-&lt;br /&gt;
| 'stop' ||	playhead position in seconds	|| Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| 'end'	|| playhead position in seconds	|| This event has to be called once for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Playhead position as integer&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' has to be called every second&lt;br /&gt;
&lt;br /&gt;
==== Example Events ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass ( Object ):''' Content Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', contentMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass  ( Object ):''' Pre-roll AD Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', prerollMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' setPlayheadPosition  |  '''Value Pass ( Integer ):''' playheadPosition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' stop  |  '''Value Pass ( Integer ):''' stopPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('stop', stopPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' end  |  '''Value Pass ( Integer ):''' endPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('end', endPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Interrupt Scenarios ==&lt;br /&gt;
&lt;br /&gt;
=== Pause Event ===&lt;br /&gt;
The setPlayheadPostion event is used for handling pause. To indicate pause, stop passing the playhead position to the SDK. Once the content resumes, begin sending the playhead again with the correct playhead value.&lt;br /&gt;
&lt;br /&gt;
=== Other Interrupt Scenarios ===&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
window.addEventListener('beforeunload', function(event) &lt;br /&gt;
{&lt;br /&gt;
  // Only inside a midroll indicate &amp;lt;stop&amp;gt; for the ad&lt;br /&gt;
  nSdkInstance.ggPM('stop', playheadPosition);&lt;br /&gt;
  &lt;br /&gt;
  // Indicate &amp;lt;end&amp;gt; and &amp;lt;stop&amp;gt; for the content&lt;br /&gt;
  nSdkInstance.ggPM('end', playheadPosition);&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===  SDK Event Lifecycle ===&lt;br /&gt;
&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
'''Note''' &lt;br /&gt;
*For Audiweb there is no need to tag ads in video stream ... please see 1st example how to use without ads!&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle without ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:even browser no ads.png]]&lt;br /&gt;
&lt;br /&gt;
==== Example without ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);  // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle with ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:event browser.png|event browser.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example with ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// PREROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end pre-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);&lt;br /&gt;
&lt;br /&gt;
// MIDROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
  &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end mid-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); &lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// POSTROLL&lt;br /&gt;
nSdkInstance.ggPM('loadmetadata', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); // end post-roll stream&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling 'stop', 'end', or 'loadmetadata'.&lt;br /&gt;
&lt;br /&gt;
'''Note :''' For Ad, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' For pre-roll ads you have to call the loadMetadata event for content at the start of stream and after the preroll&lt;br /&gt;
&lt;br /&gt;
== Nielsen Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
====Opt Back In====&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'debug'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
&lt;br /&gt;
====Example Production Initialization Call ====&lt;br /&gt;
Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;, &amp;quot;myPlayerName&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2062</id>
		<title>DCR Italy Video Browser SDK (6.0.0)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2062"/>
		<updated>2017-11-14T12:44:20Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: added missing interrupt scenarios&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID is needed. The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration from Nielsen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  apid: &amp;quot;XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot; // eg. PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
*Add Static Queue Snippet&lt;br /&gt;
*Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
===Create SDK Instance===&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization API call:&lt;br /&gt;
&lt;br /&gt;
==== Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,{nol_sdkDebug: &amp;quot;debug&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following  values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter	!! Description	!! Required !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid	&lt;br /&gt;
|| Unique ID assigned to player/site. &lt;br /&gt;
*Test: begins with ‘T’ and is used for testing &lt;br /&gt;
*Production: begins with ‘P’ and is used in live environment when testing and certification is completed&lt;br /&gt;
||Yes||'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&lt;br /&gt;
|-&lt;br /&gt;
|instanceName ||	Name of SDK instance ||Yes	 ||	&amp;quot;any string value&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug	|| Enables Nielsen console logging. Only required for testing	||Optional	|| nol_sdkDebug: &amp;quot;debug&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;apid&amp;gt;.js, will be downloaded based on the apid and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK600.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
==== Example SDK Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
*content: identify video&lt;br /&gt;
*ad: identify each ad&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type ||	Type of asset	|| &amp;quot;content&amp;quot;	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid	|| Unique ID assigned to content (max. 40 characters) || custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| program	|| Name of program (25 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| title	|| Episode title (40 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| length	|| Length of content in seconds for VOD (Video on demand). The value for live stream content is 86400 ||&lt;br /&gt;
*&amp;quot;seconds&amp;quot;– VOD&lt;br /&gt;
*&amp;quot;86400&amp;quot;– Live Stream&lt;br /&gt;
||	&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate	|| The airdate in the linear TV. Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; ||	YYYYMMDD hh:mm:ss	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode	|| Full episode flag ||	&lt;br /&gt;
*&amp;quot;y&amp;quot;– full episode&lt;br /&gt;
*&amp;quot;n&amp;quot;– non full episode	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
|adloadtype	|| type of ad load:&lt;br /&gt;
* 1) Linear – matches TV ad load &lt;br /&gt;
* 2) Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;1&amp;quot; – content with linear ads &lt;br /&gt;
*&amp;quot;2&amp;quot; – content with dynamic ads	&lt;br /&gt;
||&lt;br /&gt;
✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Example Content Object =====&lt;br /&gt;
&lt;br /&gt;
'''Note:''' all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           'content',&lt;br /&gt;
  assetid:        'VID123-123456',&lt;br /&gt;
  program:        'program name',&lt;br /&gt;
  title:          'episode title',&lt;br /&gt;
  length:         '1020',    // length in seconds (String)&lt;br /&gt;
  airdate:        '19700101 00:00:00',&lt;br /&gt;
  isfullepisode:  'y',&lt;br /&gt;
  adloadtype:     '2'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad, if ads are available during or before the stream (content) begins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example Ad Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create pre-roll ad object&lt;br /&gt;
var prerollMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: 'AD-1',&lt;br /&gt;
  type:    'preroll'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is ggPM().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
nSdkInstance.ggPM('event', parameter);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event name !! Values to pass !!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 'loadMetadata'	|| content/ad metadata object	|| Needs to be called at the beginning of each content/ad metadata object&lt;br /&gt;
|-&lt;br /&gt;
| 'setPlayheadPosition'&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;VOD (or ad ): || current position in seconds (integer) &amp;lt;br/&amp;gt;&lt;br /&gt;
*&amp;quot;Live: current UTC timestamp (seconds since January 1st 1970)&amp;lt;br/&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
Pass playhead position every second during playback&lt;br /&gt;
|-&lt;br /&gt;
| 'stop' ||	playhead position in seconds	|| Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| 'end'	|| playhead position in seconds	|| This event has to be called once for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Playhead position as integer&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' has to be called every second&lt;br /&gt;
&lt;br /&gt;
==== Example Events ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass ( Object ):''' Content Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', contentMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass  ( Object ):''' Pre-roll AD Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', prerollMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' setPlayheadPosition  |  '''Value Pass ( Integer ):''' playheadPosition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' stop  |  '''Value Pass ( Integer ):''' stopPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('stop', stopPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' end  |  '''Value Pass ( Integer ):''' endPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('end', endPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Interrupt Scenarios ==&lt;br /&gt;
&lt;br /&gt;
=== Pause Event ===&lt;br /&gt;
The setPlayheadPostion event is used for handling pause. To indicate pause, stop passing the playhead position to the SDK. Once the content resumes, begin sending the playhead again with the correct playhead value.&lt;br /&gt;
&lt;br /&gt;
=== Other Interrupt Scenarios ===&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
window.addEventListener('beforeunload', function(event) &lt;br /&gt;
{&lt;br /&gt;
  // Only inside a midroll indicate &amp;lt;stop&amp;gt; for the ad&lt;br /&gt;
  nSdkInstance.ggPM('stop', playheadPosition);&lt;br /&gt;
  &lt;br /&gt;
  // Indicate &amp;lt;end&amp;gt; and &amp;lt;stop&amp;gt; for the content&lt;br /&gt;
  nSdkInstance.ggPM('end', playheadPosition);&lt;br /&gt;
  nSdkInstance.ggPM('stop', playheadPosition);&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note:''' User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===  SDK Event Lifecycle ===&lt;br /&gt;
&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
'''Note''' &lt;br /&gt;
*For Audiweb there is no need to tag ads in video stream ... please see 1st example how to use without ads!&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle without ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:even browser no ads.png]]&lt;br /&gt;
&lt;br /&gt;
==== Example without ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);  // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle with ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:event browser.png|event browser.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example with ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// PREROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end pre-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);&lt;br /&gt;
&lt;br /&gt;
// MIDROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
  &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end mid-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); &lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// POSTROLL&lt;br /&gt;
nSdkInstance.ggPM('loadmetadata', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); // end post-roll stream&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling 'stop', 'end', or 'loadmetadata'.&lt;br /&gt;
&lt;br /&gt;
'''Note :''' For Ad, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' For pre-roll ads you have to call the loadMetadata event for content at the start of stream and after the preroll&lt;br /&gt;
&lt;br /&gt;
== Nielsen Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
====Opt Back In====&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'debug'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
&lt;br /&gt;
====Example Production Initialization Call ====&lt;br /&gt;
Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;, &amp;quot;myPlayerName&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=2061</id>
		<title>DCR Italy Video Browser SDK (6.0.1)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=2061"/>
		<updated>2017-11-14T12:39:13Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show how to integrate the Nielsen Software Development Kit (SDK) to enable Digital Content Ratings (DCR) video measurement on browser players.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID, clientid and vcid is needed. These values are provided by Nielsen.&lt;br /&gt;
&lt;br /&gt;
The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
AppID: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The clientid is your 'parent# or companyid'&lt;br /&gt;
clientid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;XX-XXXXXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The vcid is your channel id&lt;br /&gt;
vcid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&amp;quot;xXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
* Add Static Queue Snippet&lt;br /&gt;
* Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
=== Create SDK Instance ===&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
       clientid: &amp;quot;XX-XXXXXX&amp;quot;,  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
       vcid: &amp;quot;cXX&amp;quot;,            // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
       nol_sdkDebug: &amp;quot;debug&amp;quot;   // should be deleted when going live&lt;br /&gt;
    }&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following five values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site || &amp;lt;code&amp;gt;&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || &amp;lt;code&amp;gt;&amp;quot;any string value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value has to be passed in 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value has to be passed 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Nielsen console logging. Only required for testing. in 3rd parameter object || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK601.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;, nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
* content: identify video&lt;br /&gt;
* ad: identify each ad ('''for Italy there is no need to tag ads''')&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*video – &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to content (max. 40 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || &amp;lt;code&amp;gt;YYYYMMDD hh:mm:ss&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; - full episode&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt; - non-full episode&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load &amp;quot;1&amp;quot;&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI) &amp;quot;2&amp;quot;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| ✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| subbrand || subbrand/VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || Nielsen provided || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Content Object'''&lt;br /&gt;
... with all mandatory parameters - you may ignore the optional ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           &amp;quot;content&amp;quot;,&lt;br /&gt;
  assetid:        &amp;quot;VID123-123456&amp;quot;,&lt;br /&gt;
  program:        &amp;quot;program name&amp;quot;,&lt;br /&gt;
  title:          &amp;quot;episode title&amp;quot;,&lt;br /&gt;
  length:         &amp;quot;1020&amp;quot;,&lt;br /&gt;
  airdate:        &amp;quot;19700101 00:00:00&amp;quot;,&lt;br /&gt;
  isfullepisode:  &amp;quot;y&amp;quot;,&lt;br /&gt;
  adloadtype:     &amp;quot;2&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
=== Ad Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Audiweb there is no need to tag ads in video stream ... you may ignore this paragraph. If there are ads in your stream, but not tagged than simply do nothing while ad is playing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of ad || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || uniqueID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Ad Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;//create ad object&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: &amp;quot;AD-1&amp;quot;,&lt;br /&gt;
  type:    &amp;quot;preroll&amp;quot;&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''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.&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is &amp;lt;code&amp;gt;ggPM()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM('event', parameter, ...);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Number !! Values to pass !! Event Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'3'&amp;lt;/code&amp;gt; || content/ad metadata object || load content metadata || Load metadata event for content. Has to be called at the very first beginning of each stream.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'5'&amp;lt;/code&amp;gt; || playhead position || content play || Call when content or ads start playing or resumes from pause. &lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'6'&amp;lt;/code&amp;gt; || playhead position || pause || Call when content or ads is pausing. Use Event 5 to resume ...&lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt; || playhead position || stop || Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'8'&amp;lt;/code&amp;gt; || playhead position from, playhead position to || seek || Call when scrubbing forward or backward with playhead position 'from' and 'to'&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt; || content/ad metadata object || load ad metadata || Call at the beginning of each ad, don’t use ‘play’ (event 5) if event 15 is used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; || playhead position || playhead position || '''VOD''': current position in seconds. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
Note: has to be called on a secondly basis.&lt;br /&gt;
For each ad the playheads starts with 0 (no Live unix timestamp for ads)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt; || playhead position || end || This event has to be called '''once''' for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Event Lifecycle ===&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;example '''without''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': if there are ads played in stream simply use a pause (event 6) when ads start playing and a play (event 5) when content start playing.&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&amp;lt;big&amp;gt; example '''with''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// Preroll&lt;br /&gt;
nSdkInstance.ggPM('15', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Midroll&lt;br /&gt;
nSdkInstance.ggPM('15', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// Postroll&lt;br /&gt;
nSdkInstance.ggPM('15', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Italy there is no need to tag ads in video stream ... ignore &amp;quot;with ads&amp;quot; example!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': Event &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling event &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when buffering occurs you have to send a event 6 (pause) and after buffering finished a 5 (play).&lt;br /&gt;
&lt;br /&gt;
'''Note''': For Ad Pods, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note''': When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Pause'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; is used for handling pause. To indicate pause, stop passing the playhead position to the SDK and send Event 6 with playhead once. When content resumes, begin sending the playhead again with the correct playhead value. Also if buffering occurs for more than 1 second you may use Event 6 (pause) to indicate that.&lt;br /&gt;
e.g. pause at 1m2s and resume after a couple of seconds:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // now send nothing to SDK until player resumes (automatically because of buffering ends or user unpauses/resumes play&lt;br /&gt;
nSdkInstance.ggPM('5', 62); // play/5 when resume occurs (when user click play or buffering ends)&lt;br /&gt;
nSdkInstance.ggPM('49', 63);&lt;br /&gt;
nSdkInstance.ggPM('49', 64);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Seek'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; is used for handling forward/backward seek. To indicate seek, send Event 8 with 'from' and 'to' playhead.&lt;br /&gt;
e.g. seek from 1m2s to 2m0s:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // use pause, because buffering will occur (to be on safe side)&lt;br /&gt;
nSdkInstance.ggPM('8', 62,120);&lt;br /&gt;
nSdkInstance.ggPM('5', 120); // play/5 when resuming&lt;br /&gt;
nSdkInstance.ggPM('49', 120);&lt;br /&gt;
nSdkInstance.ggPM('49', 121);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Interruption Scenarios'''&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;window.addEventListener('beforeunload', function(event) &lt;br /&gt;
{&lt;br /&gt;
  // Only inside a midroll indicate 'stop' for the ad&lt;br /&gt;
  if (insideMidroll) {&lt;br /&gt;
    nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // Indicate 'end' for the content and 'stop' for the stream&lt;br /&gt;
  nSdkInstance.ggPM('57', playheadPosition);&lt;br /&gt;
  nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
});&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer or covering Safari on mobile browsers ... you may use &amp;quot;onpagehide&amp;quot; event as well).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Static_App_SDK&amp;diff=2060</id>
		<title>DCR Italy Static App SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Static_App_SDK&amp;diff=2060"/>
		<updated>2017-11-14T09:01:15Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The App SDK is the framework for mobile application developers to integrate Nielsen Measurement into their media player applications. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an application like:&lt;br /&gt;
*Application launch events and how long app was running&lt;br /&gt;
*Time of viewing a sub section / page in the application.&lt;br /&gt;
&lt;br /&gt;
==  Implementation ==&lt;br /&gt;
This guide covers implementation steps for iOS using Xcode and Java using Android Studio to enable '''STATIC MEASUREMENT''' within you APP.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites == &lt;br /&gt;
To start using the Nielsen App SDK, your Xcode or Android Studio environments need to have specific Frameworks or Classes included in your project/app.  This information is detailed in the [[DCR Italy Video App SDK]] documentation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt; The remainder of this document will assume that you have followed the steps outlined in the [[DCR Italy Video App SDK]] documentation to Initialize the Nielsen SDK.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Initialize the SDK == &lt;br /&gt;
Specific steps are outlined in the [[DCR Italy Video App SDK]] documentation.&lt;br /&gt;
&lt;br /&gt;
== Populate and Pass Metadata Object ==&lt;br /&gt;
The Nielsen SDK is able to monitor Application launch events and how long your app has been running.  Once the Nielsen SDK has been Initialized, pass &amp;lt;code&amp;gt;&amp;quot;type&amp;quot;:'static'&amp;lt;/code&amp;gt; as a JSON object via loadMetadata.&lt;br /&gt;
&lt;br /&gt;
{{ExampleCode|&lt;br /&gt;
|Swift = &amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
        let staticMetadata = [&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;static&amp;quot;,&lt;br /&gt;
            &amp;quot;assetid&amp;quot;: &amp;quot;vid345-67483&amp;quot;,&lt;br /&gt;
            &amp;quot;section&amp;quot;: &amp;quot;siteSection&amp;quot;&lt;br /&gt;
        ];&lt;br /&gt;
         self.nielsenAppApi?.loadMetadata(staticMetadata)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|Objective C = &amp;lt;syntaxhighlight lang=&amp;quot;objective-c&amp;quot;&amp;gt; &lt;br /&gt;
   NSDictionary *staticMetadata = @&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;static&amp;quot;,&lt;br /&gt;
        &amp;quot;assetid&amp;quot;: &amp;quot;vid345-67483&amp;quot;,&lt;br /&gt;
        &amp;quot;section&amp;quot;: &amp;quot;siteSection&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
– (void)loadMetadata:(id)staticMetadata;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|Android = &amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;    JSONObject staticMetadata = new JSONObject()&lt;br /&gt;
        .put(&amp;quot;type&amp;quot;, &amp;quot;static&amp;quot;)&lt;br /&gt;
        .put(&amp;quot;section&amp;quot;, &amp;quot;siteSection&amp;quot;)&lt;br /&gt;
        .put(&amp;quot;assetid&amp;quot;, &amp;quot;vid345-67483&amp;quot;)&lt;br /&gt;
    }&lt;br /&gt;
public void loadMetadata(JSONObject staticMetadata);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
The above code would be repeated for each change in &amp;quot;section&amp;quot; within your app.&lt;br /&gt;
&lt;br /&gt;
=== Nielsen SDK Metadata ===&lt;br /&gt;
The following table defines the staticMetadata reserved keys:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Data Type !! Value !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type || asset type || fixed || &amp;lt;code&amp;gt;'static'&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID for each article || dynamic || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| 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&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Handling Foreground and Background states  ==&lt;br /&gt;
For iOS, background/foreground detection is handled by the app lifecylce APIs which are provided by [https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html Apple]:&lt;br /&gt;
&lt;br /&gt;
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&lt;br /&gt;
* Enable the Nielsen SDK to measure background/foreground state by makingthe relevant update to the AndroidManifest.&lt;br /&gt;
* Integrate Nielsen’s SdkBgFgDetectionUtility class within your Custom Application Class.&lt;br /&gt;
* Custom implementation of the required methods within your application.&lt;br /&gt;
&lt;br /&gt;
=== ForeGround/Background Measurement via AndroidManifest ===&lt;br /&gt;
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.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;application android:name=”com.nielsen.app.sdk.AppSdkApplication”&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using the Android SdkBgFbDetectionUtility Class ===&lt;br /&gt;
For developers who are already using the application class, it is recommended that background/foreground state is implemented using the  [[Android_Background_Foreground|SdkBgFgDetectionUtility class]].  The  [[Android_Background_Foreground|SdkBgFgDetectionUtility class]] is compatible with Android 4+ and has been made available to Nielsen clients.&lt;br /&gt;
&lt;br /&gt;
=== Manual Background/ForeGround State Management ===&lt;br /&gt;
In cases where the developer is not able to use the AndroidManifest.xml solution nor the Nielsen provided   [[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.&lt;br /&gt;
&lt;br /&gt;
The SDK is informed about app state using the below methods.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
AppLaunchMeasurementManager.appInForeground(getApplicationContext());&lt;br /&gt;
AppLaunchMeasurementManager.appInBackground(getApplicationContext());&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Within the lifecycle of individual activities, onResume() and onPause() are best suited to providing indication of the app state.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Correct measurement of the foreground/background state is crucial to Static App measurement within Nielsen Digital Content Ratings (DCR).&lt;br /&gt;
&lt;br /&gt;
== Privacy and Opt-Out ==&lt;br /&gt;
Please follow the steps outlined in the [[DCR Italy Video App SDK|Privacy_and_Opt-Out]] documentation.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make one update to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;iOS Example:&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;swift&amp;quot;&amp;gt;&lt;br /&gt;
class NielsenInit: NSObject {&lt;br /&gt;
    class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -&amp;gt; NielsenAppApi?{&lt;br /&gt;
    let appInformation:[String: String] = [&lt;br /&gt;
            &amp;quot;appid&amp;quot;: &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;,&lt;br /&gt;
            &amp;quot;sfcode&amp;quot;: &amp;quot;it&amp;quot;&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
        ]&lt;br /&gt;
        return NielsenAppApi(appInfo:appInformation, delegate:delegate)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;big&amp;gt;Android Example:&amp;lt;/big&amp;gt;''' &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;  &lt;br /&gt;
try&lt;br /&gt;
{&lt;br /&gt;
  // Prepare AppSdk configuration object (JSONObject)&lt;br /&gt;
  JSONObject appSdkConfig = new JSONObject()&lt;br /&gt;
          .put(&amp;quot;appid&amp;quot;, &amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;)&lt;br /&gt;
          .put(&amp;quot;sfcode&amp;quot;, &amp;quot;it&amp;quot;)&lt;br /&gt;
            // Remove Flag:   &amp;quot;nol_devDebug&amp;quot;: &amp;quot;DEBUG&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Pass appSdkConfig to the AppSdk constructor&lt;br /&gt;
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);&lt;br /&gt;
}&lt;br /&gt;
catch (JSONException e)&lt;br /&gt;
{&lt;br /&gt;
  Log.e(TAG, &amp;quot;Couldn’t prepare JSONObject for appSdkConfig&amp;quot;, e);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=2059</id>
		<title>DCR Italy Video Browser SDK (6.0.1)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=2059"/>
		<updated>2017-11-09T17:04:58Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show how to integrate the Nielsen Software Development Kit (SDK) to enable Digital Content Ratings (DCR) video measurement on browser players.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID, clientid and vcid is needed. These values are provided by Nielsen.&lt;br /&gt;
&lt;br /&gt;
The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
AppID: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The clientid is your 'parent# or companyid'&lt;br /&gt;
clientid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;XX-XXXXXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The vcid is your channel id&lt;br /&gt;
vcid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&amp;quot;xXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
* Add Static Queue Snippet&lt;br /&gt;
* Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
=== Create SDK Instance ===&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
       clientid: &amp;quot;XX-XXXXXX&amp;quot;,  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
       vcid: &amp;quot;cXX&amp;quot;,            // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
       nol_sdkDebug: &amp;quot;debug&amp;quot;   // should be deleted when going live&lt;br /&gt;
    }&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following five values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site || &amp;lt;code&amp;gt;&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || &amp;lt;code&amp;gt;&amp;quot;any string value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value has to be passed in 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value has to be passed 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Nielsen console logging. Only required for testing. in 3rd parameter object || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK601.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;, nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
* content: identify video&lt;br /&gt;
* ad: identify each ad ('''for Italy there is no need to tag ads''')&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*video – &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to content (max. 40 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || &amp;lt;code&amp;gt;YYYYMMDD hh:mm:ss&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; - full episode&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt; - non-full episode&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load &amp;quot;1&amp;quot;&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI) &amp;quot;2&amp;quot;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| ✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| subbrand || subbrand/VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || Nielsen provided || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Content Object'''&lt;br /&gt;
... with all mandatory parameters - you may ignore the optional ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           &amp;quot;content&amp;quot;,&lt;br /&gt;
  assetid:        &amp;quot;VID123-123456&amp;quot;,&lt;br /&gt;
  program:        &amp;quot;program name&amp;quot;,&lt;br /&gt;
  title:          &amp;quot;episode title&amp;quot;,&lt;br /&gt;
  length:         &amp;quot;1020&amp;quot;,&lt;br /&gt;
  airdate:        &amp;quot;19700101 00:00:00&amp;quot;,&lt;br /&gt;
  isfullepisode:  &amp;quot;y&amp;quot;,&lt;br /&gt;
  adloadtype:     &amp;quot;2&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
=== Ad Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Audiweb there is no need to tag ads in video stream ... you may ignore this paragraph. If there are ads in your stream, but not tagged than simply do nothing while ad is playing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of ad || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || uniqueID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Ad Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;//create ad object&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: &amp;quot;AD-1&amp;quot;,&lt;br /&gt;
  type:    &amp;quot;preroll&amp;quot;&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''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.&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is &amp;lt;code&amp;gt;ggPM()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM('event', parameter, ...);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Number !! Values to pass !! Event Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'3'&amp;lt;/code&amp;gt; || content/ad metadata object || load content metadata || Load metadata event for content. Has to be called at the very first beginning of each stream.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'5'&amp;lt;/code&amp;gt; || playhead position || content play || Call when content or ads start playing or resumes from pause. &lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'6'&amp;lt;/code&amp;gt; || playhead position || pause || Call when content or ads is pausing. Use Event 5 to resume ...&lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt; || playhead position || stop || Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'8'&amp;lt;/code&amp;gt; || playhead position from, playhead position to || seek || Call when scrubbing forward or backward with playhead position 'from' and 'to'&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt; || content/ad metadata object || load ad metadata || Call at the beginning of each ad, don’t use ‘play’ (event 5) if event 15 is used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; || playhead position || playhead position || '''VOD''': current position in seconds. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
Note: has to be called on a secondly basis.&lt;br /&gt;
For each ad the playheads starts with 0 (no Live unix timestamp for ads)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt; || playhead position || end || This event has to be called '''once''' for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Event Lifecycle ===&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;example '''without''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': if there are ads played in stream simply use a pause (event 6) when ads start playing and a play (event 5) when content start playing.&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&amp;lt;big&amp;gt; example '''with''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// Preroll&lt;br /&gt;
nSdkInstance.ggPM('15', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Midroll&lt;br /&gt;
nSdkInstance.ggPM('15', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// Postroll&lt;br /&gt;
nSdkInstance.ggPM('15', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Italy there is no need to tag ads in video stream ... ignore &amp;quot;with ads&amp;quot; example!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': Event &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling event &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when buffering occurs you have to send a event 6 (pause) and after buffering finished a 5 (play).&lt;br /&gt;
&lt;br /&gt;
'''Note''': For Ad Pods, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note''': When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Pause'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; is used for handling pause. To indicate pause, stop passing the playhead position to the SDK and send Event 6 with playhead once. When content resumes, begin sending the playhead again with the correct playhead value. Also if buffering occurs for more than 1 second you may use Event 6 (pause) to indicate that.&lt;br /&gt;
e.g. pause at 1m2s and resume after a couple of seconds:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // now send nothing to SDK until player resumes (automatically because of buffering ends or user unpauses/resumes play&lt;br /&gt;
nSdkInstance.ggPM('5', 62); // play/5 when resume occurs (when user click play or buffering ends)&lt;br /&gt;
nSdkInstance.ggPM('49', 63);&lt;br /&gt;
nSdkInstance.ggPM('49', 64);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Seek'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; is used for handling forward/backward seek. To indicate seek, send Event 8 with 'from' and 'to' playhead.&lt;br /&gt;
e.g. seek from 1m2s to 2m0s:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // use pause, because buffering will occur (to be on safe side)&lt;br /&gt;
nSdkInstance.ggPM('8', 62,120);&lt;br /&gt;
nSdkInstance.ggPM('5', 120); // play/5 when resuming&lt;br /&gt;
nSdkInstance.ggPM('49', 120);&lt;br /&gt;
nSdkInstance.ggPM('49', 121);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Interruption Scenarios'''&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;window.addEventListener('beforeunload', function(event) &lt;br /&gt;
{&lt;br /&gt;
  // Only inside a midroll indicate 'stop' for the ad&lt;br /&gt;
  if (insideMidroll) {&lt;br /&gt;
    nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // Indicate 'end' for the content and 'stop' for the stream&lt;br /&gt;
  nSdkInstance.ggPM('57', playheadPosition);&lt;br /&gt;
  nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
});&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=2058</id>
		<title>DCR Italy Video Browser SDK (6.0.1)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=2058"/>
		<updated>2017-11-09T17:03:48Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show how to integrate the Nielsen Software Development Kit (SDK) to enable Digital Content Ratings (DCR) video measurement on browser players.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID, clientid and vcid is needed. These values are provided by Nielsen.&lt;br /&gt;
&lt;br /&gt;
The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
AppID: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The clientid is your 'parent# or companyid'&lt;br /&gt;
clientid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;XX-XXXXXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The vcid is your channel id&lt;br /&gt;
vcid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&amp;quot;xXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
* Add Static Queue Snippet&lt;br /&gt;
* Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
=== Create SDK Instance ===&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
       clientid: &amp;quot;XX-XXXXXX&amp;quot;,  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
       vcid: &amp;quot;cXX&amp;quot;,            // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
       nol_sdkDebug: &amp;quot;debug&amp;quot;   // should be deleted when going live&lt;br /&gt;
    }&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following five values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site || &amp;lt;code&amp;gt;&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || &amp;lt;code&amp;gt;&amp;quot;any string value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value has to be passed in 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value has to be passed 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Nielsen console logging. Only required for testing. in 3rd parameter object || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK601.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;, nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
* content: identify video&lt;br /&gt;
* ad: identify each ad ('''for Italy there is no need to tag ads''')&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*video – &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to content (max. 40 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || &amp;lt;code&amp;gt;YYYYMMDD hh:mm:ss&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; - full episode&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt; - non-full episode&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load &amp;quot;1&amp;quot;&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI) &amp;quot;2&amp;quot;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| ✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| subbrand || subbrand/VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || Nielsen provided || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Content Object'''&lt;br /&gt;
... with all mandatory parameters - you may ignore the optional ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           &amp;quot;content&amp;quot;,&lt;br /&gt;
  assetid:        &amp;quot;VID123-123456&amp;quot;,&lt;br /&gt;
  program:        &amp;quot;program name&amp;quot;,&lt;br /&gt;
  title:          &amp;quot;episode title&amp;quot;,&lt;br /&gt;
  length:         &amp;quot;1020&amp;quot;,&lt;br /&gt;
  airdate:        &amp;quot;19700101 00:00:00&amp;quot;,&lt;br /&gt;
  isfullepisode:  &amp;quot;y&amp;quot;,&lt;br /&gt;
  adloadtype:     &amp;quot;2&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
=== Ad Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Audiweb there is no need to tag ads in video stream ... you may ignore this paragraph. If there are ads in your stream, but not tagged than simply do nothing while ad is playing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of ad || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || uniqueID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Ad Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;//create ad object&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: &amp;quot;AD-1&amp;quot;,&lt;br /&gt;
  type:    &amp;quot;preroll&amp;quot;&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''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.&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is &amp;lt;code&amp;gt;ggPM()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM('event', parameter, ...);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Number !! Values to pass !! Event Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'3'&amp;lt;/code&amp;gt; || content/ad metadata object || load content metadata || Load metadata event for content. Has to be called at the very first beginning of each stream.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'5'&amp;lt;/code&amp;gt; || playhead position || content play || Call when content or ads start playing or resumes from pause. &lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'6'&amp;lt;/code&amp;gt; || playhead position || pause || Call when content or ads is pausing. Use Event 5 to resume ...&lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt; || playhead position || stop || Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'8'&amp;lt;/code&amp;gt; || playhead position from, playhead position to || seek || Call when scrubbing forward or backward with playhead position 'from' and 'to'&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt; || content/ad metadata object || load ad metadata || Call at the beginning of each ad, don’t use ‘play’ (event 5) if event 15 is used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; || playhead position || playhead position || '''VOD''': current position in seconds. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
Note: has to be called on a secondly basis.&lt;br /&gt;
For each ad the playheads starts with 0 (no Live unix timestamp for ads)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt; || playhead position || end || This event has to be called '''once''' for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Event Lifecycle ===&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;example '''without''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': if there are ads played in stream simply use a pause (event 6) when ads start playing and a play (event 5) when content start playing.&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&amp;lt;big&amp;gt; example '''with''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// Preroll&lt;br /&gt;
nSdkInstance.ggPM('15', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Midroll&lt;br /&gt;
nSdkInstance.ggPM('15', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// Postroll&lt;br /&gt;
nSdkInstance.ggPM('15', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Italy there is no need to tag ads in video stream ... ignore &amp;quot;with ads&amp;quot; example!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': Event &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling event &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when buffering occurs you have to send a event 6 (pause) and after buffering finished a 5 (play).&lt;br /&gt;
&lt;br /&gt;
'''Note''': For Ad Pods, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note''': When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Pause'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; is used for handling pause. To indicate pause, stop passing the playhead position to the SDK and send Event 6 with playhead once. When content resumes, begin sending the playhead again with the correct playhead value. Also if buffering occurs for more than 1 second you may use Event 6 (pause) to indicate that.&lt;br /&gt;
e.g. pause at 1m2s and resume after a couple of seconds:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // now send nothing to SDK until player resumes (automatically because of buffering ends or user unpauses/resumes play&lt;br /&gt;
nSdkInstance.ggPM('5', 62); // play/5 when resume occurs (when user click play or buffering ends)&lt;br /&gt;
nSdkInstance.ggPM('49', 63);&lt;br /&gt;
nSdkInstance.ggPM('49', 64);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Seek'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; is used for handling forward/backward seek. To indicate seek, send Event 8 with 'from' and 'to' playhead.&lt;br /&gt;
e.g. seek from 1m2s to 2m0s:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // use pause, because buffering will occur (to be on safe side)&lt;br /&gt;
nSdkInstance.ggPM('8', 62,120);&lt;br /&gt;
nSdkInstance.ggPM('5', 120); // play/5 when resuming&lt;br /&gt;
nSdkInstance.ggPM('49', 120);&lt;br /&gt;
nSdkInstance.ggPM('49', 121);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Interruption Scenarios'''&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;window.addEventListener('beforeunload', function(event) &lt;br /&gt;
{&lt;br /&gt;
  // Only inside a midroll indicate 'stop' for the ad&lt;br /&gt;
  if (insideMidroll) {&lt;br /&gt;
    nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // Indicate 'end' for the content and 'stop' for the stream&lt;br /&gt;
  nSdkInstance.ggPM('57', playheadPosition);&lt;br /&gt;
  nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
});&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Static_Browser_SDK&amp;diff=2055</id>
		<title>DCR Italy Static Browser SDK</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Static_Browser_SDK&amp;diff=2055"/>
		<updated>2017-11-09T14:28:06Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID is needed. The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;'PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Implementation Steps ==&lt;br /&gt;
=== Add Tracking Code ===&lt;br /&gt;
The Nielsen DCR Tracking Code must be added to each page.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
  // Static Queue Snippet&lt;br /&gt;
!function(t,n){t[n]=t[n]||{nlsQ:function(e,o,c,r,s,i){return s=t.document,r=s.createElement(&amp;quot;script&amp;quot;),r.async=1,r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],i.parentNode.insertBefore(r,i),t[n][o]=t[n][o]||{g:c||{},ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]}}}(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  // SDK Initialization&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX&amp;quot;,&amp;quot;nlsnInstance&amp;quot;, {nol_sdkDebug: &amp;quot;debug&amp;quot;});&lt;br /&gt;
  &lt;br /&gt;
  // Content Metadata &lt;br /&gt;
  var nielsenMetadata = {&lt;br /&gt;
    type: 'static', &lt;br /&gt;
    assetid: '', // *DYNAMIC METADATA*: unique ID for each article **REQUIRED**&lt;br /&gt;
    section: '' // *DYNAMIC METADATA*: section of site **REQUIRED**&lt;br /&gt;
    }; &lt;br /&gt;
    &lt;br /&gt;
  // Event 'staticstart' Call&lt;br /&gt;
  nSdkInstance.ggPM(&amp;quot;staticstart&amp;quot;, nielsenMetadata);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Tracking Code Components ====&lt;br /&gt;
The tracking code includes&lt;br /&gt;
* Static Queue Snippet&lt;br /&gt;
* SDK Initialization&lt;br /&gt;
* Content Metadata&lt;br /&gt;
* staticstart Event&lt;br /&gt;
&lt;br /&gt;
'''Static Queue Snippet'''&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
!function(t,n){t[n]=t[n]||&lt;br /&gt;
{&lt;br /&gt;
  nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
      return s=t.document,&lt;br /&gt;
      r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
      r.async=1,&lt;br /&gt;
      r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],i.parentNode.insertBefore(r,i),&lt;br /&gt;
      t[o]=t[o]||{g:c,ggPM:function(n,e,c,r,s){(t[o].q=t[o].q||[]).push([n,e,c,r,s])}},t[o]}&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''SDK Initialization'''&lt;br /&gt;
&lt;br /&gt;
While creating an SDK instance, initialize the SDK by calling:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX&amp;quot;, &amp;quot;&amp;quot;,{nol_sdkDebug: &amp;quot;debug&amp;quot;})&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static config file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and cached by the client-side browser(s).&lt;br /&gt;
&lt;br /&gt;
Once the static config file is downloaded, the SDK will be fully downloaded and initialized. All SDK modules are included in one file:&lt;br /&gt;
&amp;quot;nlsSDK600.bundle.min.js&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
'''Content Metadata'''&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. The tracking code includes the Nielsen reserved keys and placeholder values.&lt;br /&gt;
&lt;br /&gt;
Pass dynamic metadata for the keys with the &amp;lt;code&amp;gt;&amp;lt;metadataPlaceholder&amp;gt;&amp;lt;/code&amp;gt; value (e.g. &amp;lt;code&amp;gt;section: ''&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
'''staticstart Event'''&lt;br /&gt;
&lt;br /&gt;
There is only one event call required:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM(&amp;quot;staticstart&amp;quot;, nielsenMetadata);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The content metadata object is passed as a parameter when calling 'staticstart' event . To know more about configuring metadata refer [[Bundled_SDK_-_Static#Configure_Metadata|Step 3]].&lt;br /&gt;
&lt;br /&gt;
=== Pass App ID in Initialization Call ===&lt;br /&gt;
Pass the unique App ID in the first parameter of the initialization call, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Example SDK Initialization'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX&amp;quot;, &amp;quot;nlsnInstance&amp;quot;, {nol_sdkDebug: &amp;quot;debug&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The initialization call has three parameters:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site. || &amp;lt;code&amp;gt;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || Any string value&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug: &amp;quot;debug&amp;quot; || Enables Nielsen console logging. Only required for testing || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Update &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;&amp;lt;/code&amp;gt; with the AppID provided. Refer to the [[#Going_Live|Going Live]] section to know about updating the AppID to production after testing is completed.&lt;br /&gt;
&lt;br /&gt;
=== Configure Metadata ===&lt;br /&gt;
Map the Nielsen keys to variables so that the content metadata is dynamically updated.&lt;br /&gt;
&lt;br /&gt;
The Nielsen reserved keys are:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Data Type !! Value !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type || asset type || fixed || &amp;lt;code&amp;gt;'static'&amp;lt;/code&amp;gt; || Yes&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID for each article || dynamic || custom || Yes&lt;br /&gt;
|-&lt;br /&gt;
| 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&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings)&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement, the properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Infinite Scrolling ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;code&amp;gt;onPaginate&amp;lt;/code&amp;gt; will refire the view ping with the existing/original metadata.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM(&amp;quot;onPaginate&amp;quot;, scrolloffset);&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
{|&lt;br /&gt;
!width=&amp;quot;23%&amp;quot;| Parameter&lt;br /&gt;
!width=&amp;quot;19%&amp;quot;| Description&lt;br /&gt;
|-&lt;br /&gt;
| event&lt;br /&gt;
| &amp;lt;code&amp;gt;onPaginate&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| scrolloffset&lt;br /&gt;
| The &amp;lt;code&amp;gt;scrolloffset&amp;lt;/code&amp;gt; value should be the y-scroll position:&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== onPaginate ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;onPaginate&amp;lt;/code&amp;gt; is a slightly modified version of &amp;lt;code&amp;gt;staticstart&amp;lt;/code&amp;gt; to enable tracking of user’s focus in pages with continuous scrolling. &amp;lt;code&amp;gt;onPaginate&amp;lt;/code&amp;gt; event provides the same behavior as &amp;lt;code&amp;gt;staticstart&amp;lt;/code&amp;gt; keeping it local to only clients who wish to implement continuous scrolling. (Note: This event &amp;lt;code&amp;gt;onPaginate&amp;lt;/code&amp;gt; will not reset the page duration timer.)&lt;br /&gt;
&lt;br /&gt;
* The maximum number of static View pings allowed per session is ‘1’. This is enforced via the &amp;lt;code&amp;gt;nol_maxPingCount&amp;lt;/code&amp;gt; parameter in the tag and the cadence of impression.&lt;br /&gt;
* When an &amp;lt;code&amp;gt;onPaginate&amp;lt;/code&amp;gt; event is called at the end of section / a focus shift (within the same page), this filter will reset the current ping count to ‘0’ for the static View ping. This change of value will cause a new View ping when the Browser SDK receives the next &amp;lt;code&amp;gt;staticPosition&amp;lt;/code&amp;gt; event (at the section end). This sequence continues through the end of scrolling or till the close of static page session.&lt;br /&gt;
&lt;br /&gt;
[[File:StaticPageEvent35.jpg|center|link=]]&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''App ID''': Ensure that correct &amp;lt;apid&amp;gt; is used during initialization&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;'PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;, &amp;quot;nlsnInstance&amp;quot;);&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2054</id>
		<title>DCR Italy Video Browser SDK (6.0.0)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2054"/>
		<updated>2017-11-09T14:26:31Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID is needed. The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration from Nielsen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  apid: &amp;quot;XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot; // eg. PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
*Add Static Queue Snippet&lt;br /&gt;
*Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
===Create SDK Instance===&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization API call:&lt;br /&gt;
&lt;br /&gt;
==== Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,{nol_sdkDebug: &amp;quot;debug&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following  values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter	!! Description	!! Required !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid	&lt;br /&gt;
|| Unique ID assigned to player/site. &lt;br /&gt;
*Test: begins with ‘T’ and is used for testing &lt;br /&gt;
*Production: begins with ‘P’ and is used in live environment when testing and certification is completed&lt;br /&gt;
||Yes||'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&lt;br /&gt;
|-&lt;br /&gt;
|instanceName ||	Name of SDK instance ||Yes	 ||	&amp;quot;any string value&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug	|| Enables Nielsen console logging. Only required for testing	||Optional	|| nol_sdkDebug: &amp;quot;debug&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;apid&amp;gt;.js, will be downloaded based on the apid and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK600.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
==== Example SDK Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
*content: identify video&lt;br /&gt;
*ad: identify each ad&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type ||	Type of asset	|| &amp;quot;content&amp;quot;	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid	|| Unique ID assigned to content (max. 40 characters) || custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| program	|| Name of program (25 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| title	|| Episode title (40 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| length	|| Length of content in seconds for VOD (Video on demand). The value for live stream content is 86400 ||&lt;br /&gt;
*&amp;quot;seconds&amp;quot;– VOD&lt;br /&gt;
*&amp;quot;86400&amp;quot;– Live Stream&lt;br /&gt;
||	&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate	|| The airdate in the linear TV. Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; ||	YYYYMMDD hh:mm:ss	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode	|| Full episode flag ||	&lt;br /&gt;
*&amp;quot;y&amp;quot;– full episode&lt;br /&gt;
*&amp;quot;n&amp;quot;– non full episode	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
|adloadtype	|| type of ad load:&lt;br /&gt;
* 1) Linear – matches TV ad load &lt;br /&gt;
* 2) Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;1&amp;quot; – content with linear ads &lt;br /&gt;
*&amp;quot;2&amp;quot; – content with dynamic ads	&lt;br /&gt;
||&lt;br /&gt;
✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Example Content Object =====&lt;br /&gt;
&lt;br /&gt;
'''Note:''' all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           'content',&lt;br /&gt;
  assetid:        'VID123-123456',&lt;br /&gt;
  program:        'program name',&lt;br /&gt;
  title:          'episode title',&lt;br /&gt;
  length:         '1020',    // length in seconds (String)&lt;br /&gt;
  airdate:        '19700101 00:00:00',&lt;br /&gt;
  isfullepisode:  'y',&lt;br /&gt;
  adloadtype:     '2'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad, if ads are available during or before the stream (content) begins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example Ad Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create pre-roll ad object&lt;br /&gt;
var prerollMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: 'AD-1',&lt;br /&gt;
  type:    'preroll'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is ggPM().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
nSdkInstance.ggPM('event', parameter);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event name !! Values to pass !!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 'loadMetadata'	|| content/ad metadata object	|| Needs to be called at the beginning of each content/ad metadata object&lt;br /&gt;
|-&lt;br /&gt;
| 'setPlayheadPosition'&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;VOD (or ad ): || current position in seconds (integer) &amp;lt;br/&amp;gt;&lt;br /&gt;
*&amp;quot;Live: current UTC timestamp (seconds since January 1st 1970)&amp;lt;br/&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
Pass playhead position every second during playback&lt;br /&gt;
|-&lt;br /&gt;
| 'stop' ||	playhead position in seconds	|| Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| 'end'	|| playhead position in seconds	|| This event has to be called once for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Playhead position as integer&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' has to be called every second&lt;br /&gt;
&lt;br /&gt;
==== Example Events ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass ( Object ):''' Content Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', contentMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass  ( Object ):''' Pre-roll AD Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', prerollMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' setPlayheadPosition  |  '''Value Pass ( Integer ):''' playheadPosition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' stop  |  '''Value Pass ( Integer ):''' stopPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('stop', stopPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' end  |  '''Value Pass ( Integer ):''' endPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('end', endPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===  SDK Event Lifecycle ===&lt;br /&gt;
&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
'''Note''' &lt;br /&gt;
*For Audiweb there is no need to tag ads in video stream ... please see 1st example how to use without ads!&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle without ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:even browser no ads.png]]&lt;br /&gt;
&lt;br /&gt;
==== Example without ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);  // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle with ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:event browser.png|event browser.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example with ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// PREROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end pre-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);&lt;br /&gt;
&lt;br /&gt;
// MIDROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
  &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end mid-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); &lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// POSTROLL&lt;br /&gt;
nSdkInstance.ggPM('loadmetadata', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); // end post-roll stream&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling 'stop', 'end', or 'loadmetadata'.&lt;br /&gt;
&lt;br /&gt;
'''Note :''' For Ad, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' For pre-roll ads you have to call the loadMetadata event for content at the start of stream and after the preroll&lt;br /&gt;
&lt;br /&gt;
== Nielsen Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
====Opt Back In====&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'debug'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
&lt;br /&gt;
====Example Production Initialization Call ====&lt;br /&gt;
Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;, &amp;quot;myPlayerName&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2053</id>
		<title>DCR Italy Video Browser SDK (6.0.0)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.0)&amp;diff=2053"/>
		<updated>2017-11-09T14:25:43Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: added overview&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
The Nielsen SDK is one of multiple framework SDKs that Nielsen provides to enable measuring linear (live) and on-demand TV viewing using TVs, mobile devices, etc.&lt;br /&gt;
The Browser SDK is the framework for browsers developers to integrate Nielsen Measurement into their media player pages. It supports a variety of Nielsen Measurement Products like Digital in TV Ratings, Digital Content Ratings ([[DCR &amp;amp; DTVR]]), [[Digital Ad Ratings]] (DAR), [[Digital Audio]]. Nielsen SDKs are also equipped to measure static content and can track key life cycle events of an pages like:&lt;br /&gt;
*Site launch events and how long page is viewed&lt;br /&gt;
*Time of viewing a sub section / page.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID is needed. The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration from Nielsen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  apid: &amp;quot;XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot; // eg. PDA7D5EE6-B1B8-XXXX-XXXX-2A788BCXXXCA&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
*Add Static Queue Snippet&lt;br /&gt;
*Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
===Create SDK Instance===&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization API call:&lt;br /&gt;
&lt;br /&gt;
==== Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,{nol_sdkDebug: &amp;quot;debug&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following  values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter	!! Description	!! Required !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid	&lt;br /&gt;
|| Unique ID assigned to player/site. &lt;br /&gt;
*Test: begins with ‘T’ and is used for testing &lt;br /&gt;
*Production: begins with ‘P’ and is used in live environment when testing and certification is completed&lt;br /&gt;
||Yes||'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'&lt;br /&gt;
|-&lt;br /&gt;
|instanceName ||	Name of SDK instance ||Yes	 ||	&amp;quot;any string value&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug	|| Enables Nielsen console logging. Only required for testing	||Optional	|| nol_sdkDebug: &amp;quot;debug&amp;quot;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;apid&amp;gt;.js, will be downloaded based on the apid and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK600.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
==== Example SDK Initialization API Call ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
 var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
*content: identify video&lt;br /&gt;
*ad: identify each ad&lt;br /&gt;
&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
==== Content Metadata ====&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !!	Values	 !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type ||	Type of asset	|| &amp;quot;content&amp;quot;	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid	|| Unique ID assigned to content (max. 40 characters) || custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| program	|| Name of program (25 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| title	|| Episode title (40 characters limit)	|| custom	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| length	|| Length of content in seconds for VOD (Video on demand). The value for live stream content is 86400 ||&lt;br /&gt;
*&amp;quot;seconds&amp;quot;– VOD&lt;br /&gt;
*&amp;quot;86400&amp;quot;– Live Stream&lt;br /&gt;
||	&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate	|| The airdate in the linear TV. Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; ||	YYYYMMDD hh:mm:ss	|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode	|| Full episode flag ||	&lt;br /&gt;
*&amp;quot;y&amp;quot;– full episode&lt;br /&gt;
*&amp;quot;n&amp;quot;– non full episode	&lt;br /&gt;
||&lt;br /&gt;
✓&lt;br /&gt;
|-&lt;br /&gt;
|adloadtype	|| type of ad load:&lt;br /&gt;
* 1) Linear – matches TV ad load &lt;br /&gt;
* 2) Dynamic – Dynamic Ad Insertion (DAI)&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;1&amp;quot; – content with linear ads &lt;br /&gt;
*&amp;quot;2&amp;quot; – content with dynamic ads	&lt;br /&gt;
||&lt;br /&gt;
✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===== Example Content Object =====&lt;br /&gt;
&lt;br /&gt;
'''Note:''' all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           'content',&lt;br /&gt;
  assetid:        'VID123-123456',&lt;br /&gt;
  program:        'program name',&lt;br /&gt;
  title:          'episode title',&lt;br /&gt;
  length:         '1020',    // length in seconds (String)&lt;br /&gt;
  airdate:        '19700101 00:00:00',&lt;br /&gt;
  isfullepisode:  'y',&lt;br /&gt;
  adloadtype:     '2'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ad Metadata Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad, if ads are available during or before the stream (content) begins.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys	!! Description	!! Values	!! Required&lt;br /&gt;
|-&lt;br /&gt;
| type	|| type of ad	|| 'preroll', 'midroll', or 'postroll' ||	✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid ||	unique ID assigned to ad	|| custom	|| ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Example Ad Object ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create pre-roll ad object&lt;br /&gt;
var prerollMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: 'AD-1',&lt;br /&gt;
  type:    'preroll'&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is ggPM().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
nSdkInstance.ggPM('event', parameter);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event name !! Values to pass !!  Description&lt;br /&gt;
|-&lt;br /&gt;
| 'loadMetadata'	|| content/ad metadata object	|| Needs to be called at the beginning of each content/ad metadata object&lt;br /&gt;
|-&lt;br /&gt;
| 'setPlayheadPosition'&lt;br /&gt;
||&lt;br /&gt;
*&amp;quot;VOD (or ad ): || current position in seconds (integer) &amp;lt;br/&amp;gt;&lt;br /&gt;
*&amp;quot;Live: current UTC timestamp (seconds since January 1st 1970)&amp;lt;br/&amp;gt;&lt;br /&gt;
||&lt;br /&gt;
Pass playhead position every second during playback&lt;br /&gt;
|-&lt;br /&gt;
| 'stop' ||	playhead position in seconds	|| Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| 'end'	|| playhead position in seconds	|| This event has to be called once for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' Playhead position as integer&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' has to be called every second&lt;br /&gt;
&lt;br /&gt;
==== Example Events ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass ( Object ):''' Content Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', contentMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' loadMetadata  |  '''Value Pass  ( Object ):''' Pre-roll AD Metadata Object&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('loadMetadata', prerollMetadataObject); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' setPlayheadPosition  |  '''Value Pass ( Integer ):''' playheadPosition&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' stop  |  '''Value Pass ( Integer ):''' stopPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('stop', stopPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''Event:''' end  |  '''Value Pass ( Integer ):''' endPlayheadPosition &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
  nSdkInstance.ggPM('end', endPlayheadPosition); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===  SDK Event Lifecycle ===&lt;br /&gt;
&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
'''Note''' &lt;br /&gt;
*For Audiweb there is no need to tag ads in video stream ... please see 1st example how to use without ads!&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle without ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:even browser no ads.png]]&lt;br /&gt;
&lt;br /&gt;
==== Example without ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);  // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&lt;br /&gt;
==== Event Lifecycle with ads: ====&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
[[File:event browser.png|event browser.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Example with ads: ====&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// START OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// PREROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end pre-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);&lt;br /&gt;
&lt;br /&gt;
// MIDROLL&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
  &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition);  // end mid-roll stream&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// CONTENT&lt;br /&gt;
nSdkInstance.ggPM('loadMetadata', contentMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); &lt;br /&gt;
nSdkInstance.ggPM('end', endPlayheadPosition);  // has to be called here at the end of the content&lt;br /&gt;
// endPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
 &lt;br /&gt;
// POSTROLL&lt;br /&gt;
nSdkInstance.ggPM('loadmetadata', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', playheadPosition);  // must be fired every second with playhead starting from 0&lt;br /&gt;
&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
 &lt;br /&gt;
nSdkInstance.ggPM('setPlayheadPosition', lastPlayheadPosition); // end post-roll stream&lt;br /&gt;
// END OF STREAM&lt;br /&gt;
nSdkInstance.ggPM('stop', stopPlayheadPosition);  // stopPlayheadPosition = lastPlayheadPosition&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
'''Note:''' 'setPlayheadPosition' is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling 'stop', 'end', or 'loadmetadata'.&lt;br /&gt;
&lt;br /&gt;
'''Note :''' For Ad, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
'''Note:''' For pre-roll ads you have to call the loadMetadata event for content at the start of stream and after the preroll&lt;br /&gt;
&lt;br /&gt;
== Nielsen Opt-Out ==&lt;br /&gt;
&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
====Opt Back In====&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'debug'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
&lt;br /&gt;
====Example Production Initialization Call ====&lt;br /&gt;
Refer to the production initialization call below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;, &amp;quot;myPlayerName&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=International&amp;diff=1980</id>
		<title>International</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=International&amp;diff=1980"/>
		<updated>2017-11-08T16:11:41Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
{{CategoryIcon|International.png|International}}&lt;br /&gt;
&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;This section is under maintenance. Please contact your Nielsen representative for documentation if the guides for your country aren't listed.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; | Italy&lt;br /&gt;
! style=&amp;quot;width: 90px;&amp;quot; |&lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | &lt;br /&gt;
! style=&amp;quot;width: 45px;&amp;quot; | OS&lt;br /&gt;
!| Guide&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;5&amp;quot; | {{SmallIcon|ITFlagIcon.png}}&lt;br /&gt;
| rowspan=&amp;quot;5&amp;quot; | {{SmallIcon|SDKIcon.png}}&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | {{OSIcon|VideoIcon.png}}&lt;br /&gt;
| {{OSIcon|macOSIcon.png}}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{OSIcon|AndroidIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Video App SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
| {{OSIcon|BrowserIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Video Browser SDK (6.0.1)]] for Object Video users'''&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | {{OSIcon|StaticIcon.png}}&lt;br /&gt;
| {{OSIcon|macOSIcon.png}}&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
{{OSIcon|AndroidIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Static App SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;2&amp;quot; | {{OSIcon|BrowserIcon.png}}&lt;br /&gt;
| '''[[DCR Italy Static Browser SDK]]'''&lt;br /&gt;
|-&lt;br /&gt;
| '''[[DCR Italy Static Browser SDK (6.0.1)]]'''&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1966</id>
		<title>DCR Italy Video Browser SDK (6.0.1)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1966"/>
		<updated>2017-11-08T15:20:08Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show how to integrate the Nielsen Software Development Kit (SDK) to enable Digital Content Ratings (DCR) video measurement on browser players.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID, clientid and vcid is needed. These values are provided by Nielsen.&lt;br /&gt;
&lt;br /&gt;
The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
AppID: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The clientid is your 'parent# or companyid'&lt;br /&gt;
clientid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;XX-XXXXXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The vcid is your channel id&lt;br /&gt;
vcid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&amp;quot;xXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
* Add Static Queue Snippet&lt;br /&gt;
* Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
=== Create SDK Instance ===&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
       clientid: &amp;quot;XX-XXXXXX&amp;quot;,  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
       vcid: &amp;quot;cXX&amp;quot;,            // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
       nol_sdkDebug: &amp;quot;debug&amp;quot;   // should be deleted when going live&lt;br /&gt;
    }&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following five values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site || &amp;lt;code&amp;gt;&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || &amp;lt;code&amp;gt;&amp;quot;any string value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value has to be passed in 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value has to be passed 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Nielsen console logging. Only required for testing. in 3rd parameter object || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK601.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;, nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
* content: identify video&lt;br /&gt;
* ad: identify each ad ('''for Italy there is no need to tag ads''')&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*video – &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to content (max. 40 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || &amp;lt;code&amp;gt;YYYYMMDD hh:mm:ss&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; - full episode&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt; - non-full episode&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load &amp;quot;1&amp;quot;&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI) &amp;quot;2&amp;quot;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| ✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| subbrand || subbrand/VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || Nielsen provided || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Content Object'''&lt;br /&gt;
... with all mandatory parameters - you may ignore the optional ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           &amp;quot;content&amp;quot;,&lt;br /&gt;
  assetid:        &amp;quot;VID123-123456&amp;quot;,&lt;br /&gt;
  program:        &amp;quot;program name&amp;quot;,&lt;br /&gt;
  title:          &amp;quot;episode title&amp;quot;,&lt;br /&gt;
  length:         &amp;quot;1020&amp;quot;,&lt;br /&gt;
  airdate:        &amp;quot;19700101 00:00:00&amp;quot;,&lt;br /&gt;
  isfullepisode:  &amp;quot;y&amp;quot;,&lt;br /&gt;
  adloadtype:     &amp;quot;2&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
'''Note''': for Audiweb clients there is no need to use &amp;quot;mediaURL&amp;quot;, &amp;quot;segB&amp;quot;, &amp;quot;segC&amp;quot;, &amp;quot;crossId1&amp;quot;, &amp;quot;crossId2&amp;quot; and &amp;quot;hasAds&amp;quot;. These parameters can be left out completely from structure. They are optional and not mandatory (and out of current reporting too).&lt;br /&gt;
&lt;br /&gt;
=== Ad Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Audiweb there is no need to tag ads in video stream ... you may ignore this paragraph. If there are ads in your stream, but not tagged than simply do nothing while ad is playing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of ad || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || uniqueID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Ad Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;//create ad object&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: &amp;quot;AD-1&amp;quot;,&lt;br /&gt;
  type:    &amp;quot;preroll&amp;quot;&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''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.&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is &amp;lt;code&amp;gt;ggPM()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM('event', parameter, ...);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Number !! Values to pass !! Event Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'3'&amp;lt;/code&amp;gt; || content/ad metadata object || load content metadata || Load metadata event for content. Has to be called at the very first beginning of each stream.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'5'&amp;lt;/code&amp;gt; || playhead position || content play || Call when content or ads start playing or resumes from pause. &lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'6'&amp;lt;/code&amp;gt; || playhead position || pause || Call when content or ads is pausing. Use Event 5 to resume ...&lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt; || playhead position || stop || Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'8'&amp;lt;/code&amp;gt; || playhead position from, playhead position to || seek || Call when scrubbing forward or backward with playhead position 'from' and 'to'&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt; || content/ad metadata object || load ad metadata || Call at the beginning of each ad, don’t use ‘play’ (event 5) if event 15 is used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; || playhead position || playhead position || '''VOD''': current position in seconds. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
Note: has to be called on a secondly basis.&lt;br /&gt;
For each ad the playheads starts with 0 (no Live unix timestamp for ads)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt; || playhead position || end || This event has to be called '''once''' for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Event Lifecycle ===&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;example '''without''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': if there are ads played in stream simply use a pause (event 6) when ads start playing and a play (event 5) when content start playing.&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&amp;lt;big&amp;gt; example '''with''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// Preroll&lt;br /&gt;
nSdkInstance.ggPM('15', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Midroll&lt;br /&gt;
nSdkInstance.ggPM('15', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// Postroll&lt;br /&gt;
nSdkInstance.ggPM('15', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Italy there is no need to tag ads in video stream ... ignore &amp;quot;with ads&amp;quot; example!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': Event &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling event &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when buffering occurs you have to send a event 6 (pause) and after buffering finished a 5 (play).&lt;br /&gt;
&lt;br /&gt;
'''Note''': For Ad Pods, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note''': When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Pause'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; is used for handling pause. To indicate pause, stop passing the playhead position to the SDK and send Event 6 with playhead once. When content resumes, begin sending the playhead again with the correct playhead value. Also if buffering occurs for more than 1 second you may use Event 6 (pause) to indicate that.&lt;br /&gt;
e.g. pause at 1m2s and resume after a couple of seconds:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // now send nothing to SDK until player resumes (automatically because of buffering ends or user unpauses/resumes play&lt;br /&gt;
nSdkInstance.ggPM('5', 62); // play/5 when resume occurs (when user click play or buffering ends)&lt;br /&gt;
nSdkInstance.ggPM('49', 63);&lt;br /&gt;
nSdkInstance.ggPM('49', 64);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Seek'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; is used for handling forward/backward seek. To indicate seek, send Event 8 with 'from' and 'to' playhead.&lt;br /&gt;
e.g. seek from 1m2s to 2m0s:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // use pause, because buffering will occur (to be on safe side)&lt;br /&gt;
nSdkInstance.ggPM('8', 62,120);&lt;br /&gt;
nSdkInstance.ggPM('5', 120); // play/5 when resuming&lt;br /&gt;
nSdkInstance.ggPM('49', 120);&lt;br /&gt;
nSdkInstance.ggPM('49', 121);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Interruption Scenarios'''&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;window.addEventListener('beforeunload', function(event) &lt;br /&gt;
{&lt;br /&gt;
  // Only inside a midroll indicate 'stop' for the ad&lt;br /&gt;
  if (insideMidroll) {&lt;br /&gt;
    nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // Indicate 'end' for the content and 'stop' for the stream&lt;br /&gt;
  nSdkInstance.ggPM('57', playheadPosition);&lt;br /&gt;
  nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
});&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Once the DCR Tracking Code is added to Instant Articles, Nielsen will validate the implementation. Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1965</id>
		<title>DCR Italy Video Browser SDK (6.0.1)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1965"/>
		<updated>2017-11-08T15:19:33Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show how to integrate the Nielsen Software Development Kit (SDK) to enable Digital Content Ratings (DCR) video measurement on browser players.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID, clientid and vcid is needed. These values are provided by Nielsen.&lt;br /&gt;
&lt;br /&gt;
The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
AppID: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The clientid is your 'parent# or companyid'&lt;br /&gt;
clientid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;XX-XXXXXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The vcid is your channel id&lt;br /&gt;
vcid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&amp;quot;xXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
* Add Static Queue Snippet&lt;br /&gt;
* Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
=== Create SDK Instance ===&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
       clientid: &amp;quot;XX-XXXXXX&amp;quot;,  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
       vcid: &amp;quot;cXX&amp;quot;,            // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
       nol_sdkDebug: &amp;quot;debug&amp;quot;   // should be deleted when going live&lt;br /&gt;
    }&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following five values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site || &amp;lt;code&amp;gt;&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || &amp;lt;code&amp;gt;&amp;quot;any string value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value has to be passed in 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value has to be passed 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Nielsen console logging. Only required for testing. in 3rd parameter object || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK601.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;, nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
* content: identify video&lt;br /&gt;
* ad: identify each ad ('''for Italy there is no need to tag ads''')&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*video – &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to content (max. 40 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || &amp;lt;code&amp;gt;YYYYMMDD hh:mm:ss&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; - full episode&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt; - non-full episode&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load &amp;quot;1&amp;quot;&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI) &amp;quot;2&amp;quot;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| ✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| subbrand || subbrand/VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || Nielsen provided || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Content Object'''&lt;br /&gt;
... with all mandatory parameters - you may ignore the optional ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           &amp;quot;content&amp;quot;,&lt;br /&gt;
  assetid:        &amp;quot;VID123-123456&amp;quot;,&lt;br /&gt;
  program:        &amp;quot;program name&amp;quot;,&lt;br /&gt;
  title:          &amp;quot;episode title&amp;quot;,&lt;br /&gt;
  length:         &amp;quot;1020&amp;quot;,&lt;br /&gt;
  airdate:        &amp;quot;19700101 00:00:00&amp;quot;,&lt;br /&gt;
  isfullepisode:  &amp;quot;y&amp;quot;,&lt;br /&gt;
  adloadtype: &amp;quot;2&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
'''Note''': for Audiweb clients there is no need to use &amp;quot;mediaURL&amp;quot;, &amp;quot;segB&amp;quot;, &amp;quot;segC&amp;quot;, &amp;quot;crossId1&amp;quot;, &amp;quot;crossId2&amp;quot; and &amp;quot;hasAds&amp;quot;. These parameters can be left out completely from structure. They are optional and not mandatory (and out of current reporting too).&lt;br /&gt;
&lt;br /&gt;
=== Ad Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Audiweb there is no need to tag ads in video stream ... you may ignore this paragraph. If there are ads in your stream, but not tagged than simply do nothing while ad is playing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of ad || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || uniqueID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Ad Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;//create ad object&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: &amp;quot;AD-1&amp;quot;,&lt;br /&gt;
  type:    &amp;quot;preroll&amp;quot;&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''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.&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is &amp;lt;code&amp;gt;ggPM()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM('event', parameter, ...);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Number !! Values to pass !! Event Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'3'&amp;lt;/code&amp;gt; || content/ad metadata object || load content metadata || Load metadata event for content. Has to be called at the very first beginning of each stream.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'5'&amp;lt;/code&amp;gt; || playhead position || content play || Call when content or ads start playing or resumes from pause. &lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'6'&amp;lt;/code&amp;gt; || playhead position || pause || Call when content or ads is pausing. Use Event 5 to resume ...&lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt; || playhead position || stop || Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'8'&amp;lt;/code&amp;gt; || playhead position from, playhead position to || seek || Call when scrubbing forward or backward with playhead position 'from' and 'to'&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt; || content/ad metadata object || load ad metadata || Call at the beginning of each ad, don’t use ‘play’ (event 5) if event 15 is used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; || playhead position || playhead position || '''VOD''': current position in seconds. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
Note: has to be called on a secondly basis.&lt;br /&gt;
For each ad the playheads starts with 0 (no Live unix timestamp for ads)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt; || playhead position || end || This event has to be called '''once''' for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Event Lifecycle ===&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;example '''without''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': if there are ads played in stream simply use a pause (event 6) when ads start playing and a play (event 5) when content start playing.&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&amp;lt;big&amp;gt; example '''with''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// Preroll&lt;br /&gt;
nSdkInstance.ggPM('15', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Midroll&lt;br /&gt;
nSdkInstance.ggPM('15', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// Postroll&lt;br /&gt;
nSdkInstance.ggPM('15', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Italy there is no need to tag ads in video stream ... ignore &amp;quot;with ads&amp;quot; example!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': Event &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling event &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when buffering occurs you have to send a event 6 (pause) and after buffering finished a 5 (play).&lt;br /&gt;
&lt;br /&gt;
'''Note''': For Ad Pods, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note''': When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Pause'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; is used for handling pause. To indicate pause, stop passing the playhead position to the SDK and send Event 6 with playhead once. When content resumes, begin sending the playhead again with the correct playhead value. Also if buffering occurs for more than 1 second you may use Event 6 (pause) to indicate that.&lt;br /&gt;
e.g. pause at 1m2s and resume after a couple of seconds:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // now send nothing to SDK until player resumes (automatically because of buffering ends or user unpauses/resumes play&lt;br /&gt;
nSdkInstance.ggPM('5', 62); // play/5 when resume occurs (when user click play or buffering ends)&lt;br /&gt;
nSdkInstance.ggPM('49', 63);&lt;br /&gt;
nSdkInstance.ggPM('49', 64);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Seek'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; is used for handling forward/backward seek. To indicate seek, send Event 8 with 'from' and 'to' playhead.&lt;br /&gt;
e.g. seek from 1m2s to 2m0s:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // use pause, because buffering will occur (to be on safe side)&lt;br /&gt;
nSdkInstance.ggPM('8', 62,120);&lt;br /&gt;
nSdkInstance.ggPM('5', 120); // play/5 when resuming&lt;br /&gt;
nSdkInstance.ggPM('49', 120);&lt;br /&gt;
nSdkInstance.ggPM('49', 121);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Interruption Scenarios'''&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;window.addEventListener('beforeunload', function(event) &lt;br /&gt;
{&lt;br /&gt;
  // Only inside a midroll indicate 'stop' for the ad&lt;br /&gt;
  if (insideMidroll) {&lt;br /&gt;
    nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // Indicate 'end' for the content and 'stop' for the stream&lt;br /&gt;
  nSdkInstance.ggPM('57', playheadPosition);&lt;br /&gt;
  nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
});&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Once the DCR Tracking Code is added to Instant Articles, Nielsen will validate the implementation. Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1964</id>
		<title>DCR Italy Video Browser SDK (6.0.1)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1964"/>
		<updated>2017-11-08T15:13:34Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show how to integrate the Nielsen Software Development Kit (SDK) to enable Digital Content Ratings (DCR) video measurement on browser players.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID, clientid and vcid is needed. These values are provided by Nielsen.&lt;br /&gt;
&lt;br /&gt;
The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
AppID: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The clientid is your 'parent# or companyid'&lt;br /&gt;
clientid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;XX-XXXXXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The vcid is your channel id&lt;br /&gt;
vcid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&amp;quot;xXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
* Add Static Queue Snippet&lt;br /&gt;
* Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
=== Create SDK Instance ===&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
       clientid: &amp;quot;XX-XXXXXX&amp;quot;,  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
       vcid: &amp;quot;cXX&amp;quot;,            // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
       nol_sdkDebug: &amp;quot;debug&amp;quot;   // should be deleted when going live&lt;br /&gt;
    }&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following five values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site || &amp;lt;code&amp;gt;&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || &amp;lt;code&amp;gt;&amp;quot;any string value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value has to be passed in 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value has to be passed 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Nielsen console logging. Only required for testing. in 3rd parameter object || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK601.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;, nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
* content: identify video&lt;br /&gt;
* ad: identify each ad ('''for Italy there is no need to tag ads''')&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*video – &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to content (max. 40 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || &amp;lt;code&amp;gt;YYYYMMDD hh:mm:ss&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; - full episode&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt; - non-full episode&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load &amp;quot;1&amp;quot;&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI) &amp;quot;2&amp;quot;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| ✓ (has to be &amp;quot;2&amp;quot; for DCR/Italy)&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| subbrand || subbrand/VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || Nielsen provided || &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Content Object'''&lt;br /&gt;
... with all mandatory parameters - you may ignore the optional ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           &amp;quot;content&amp;quot;,&lt;br /&gt;
  assetid:        &amp;quot;VID123-123456&amp;quot;,&lt;br /&gt;
  program:        &amp;quot;program name&amp;quot;,&lt;br /&gt;
  title:          &amp;quot;episode title&amp;quot;,&lt;br /&gt;
  length:         &amp;quot;1020&amp;quot;,&lt;br /&gt;
  airdate:        &amp;quot;19700101 00:00:00&amp;quot;,&lt;br /&gt;
  isfullepisode:  &amp;quot;y&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
'''Note''': for Audiweb clients there is no need to use &amp;quot;mediaURL&amp;quot;, &amp;quot;segB&amp;quot;, &amp;quot;segC&amp;quot;, &amp;quot;crossId1&amp;quot;, &amp;quot;crossId2&amp;quot; and &amp;quot;hasAds&amp;quot;. These parameters can be left out completely from structure. They are optional and not mandatory (and out of current reporting too).&lt;br /&gt;
&lt;br /&gt;
=== Ad Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Audiweb there is no need to tag ads in video stream ... you may ignore this paragraph. If there are ads in your stream, but not tagged than simply do nothing while ad is playing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of ad || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || uniqueID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Ad Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;//create ad object&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: &amp;quot;AD-1&amp;quot;,&lt;br /&gt;
  type:    &amp;quot;preroll&amp;quot;&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''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.&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is &amp;lt;code&amp;gt;ggPM()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM('event', parameter, ...);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Number !! Values to pass !! Event Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'3'&amp;lt;/code&amp;gt; || content/ad metadata object || load content metadata || Load metadata event for content. Has to be called at the very first beginning of each stream.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'5'&amp;lt;/code&amp;gt; || playhead position || content play || Call when content or ads start playing or resumes from pause. &lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'6'&amp;lt;/code&amp;gt; || playhead position || pause || Call when content or ads is pausing. Use Event 5 to resume ...&lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt; || playhead position || stop || Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'8'&amp;lt;/code&amp;gt; || playhead position from, playhead position to || seek || Call when scrubbing forward or backward with playhead position 'from' and 'to'&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt; || content/ad metadata object || load ad metadata || Call at the beginning of each ad, don’t use ‘play’ (event 5) if event 15 is used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; || playhead position || playhead position || '''VOD''': current position in seconds. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
Note: has to be called on a secondly basis.&lt;br /&gt;
For each ad the playheads starts with 0 (no Live unix timestamp for ads)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt; || playhead position || end || This event has to be called '''once''' for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Event Lifecycle ===&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;example '''without''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': if there are ads played in stream simply use a pause (event 6) when ads start playing and a play (event 5) when content start playing.&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&amp;lt;big&amp;gt; example '''with''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// Preroll&lt;br /&gt;
nSdkInstance.ggPM('15', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Midroll&lt;br /&gt;
nSdkInstance.ggPM('15', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// Postroll&lt;br /&gt;
nSdkInstance.ggPM('15', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Italy there is no need to tag ads in video stream ... ignore &amp;quot;with ads&amp;quot; example!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': Event &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling event &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when buffering occurs you have to send a event 6 (pause) and after buffering finished a 5 (play).&lt;br /&gt;
&lt;br /&gt;
'''Note''': For Ad Pods, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note''': When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Pause'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; is used for handling pause. To indicate pause, stop passing the playhead position to the SDK and send Event 6 with playhead once. When content resumes, begin sending the playhead again with the correct playhead value. Also if buffering occurs for more than 1 second you may use Event 6 (pause) to indicate that.&lt;br /&gt;
e.g. pause at 1m2s and resume after a couple of seconds:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // now send nothing to SDK until player resumes (automatically because of buffering ends or user unpauses/resumes play&lt;br /&gt;
nSdkInstance.ggPM('5', 62); // play/5 when resume occurs (when user click play or buffering ends)&lt;br /&gt;
nSdkInstance.ggPM('49', 63);&lt;br /&gt;
nSdkInstance.ggPM('49', 64);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Seek'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; is used for handling forward/backward seek. To indicate seek, send Event 8 with 'from' and 'to' playhead.&lt;br /&gt;
e.g. seek from 1m2s to 2m0s:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // use pause, because buffering will occur (to be on safe side)&lt;br /&gt;
nSdkInstance.ggPM('8', 62,120);&lt;br /&gt;
nSdkInstance.ggPM('5', 120); // play/5 when resuming&lt;br /&gt;
nSdkInstance.ggPM('49', 120);&lt;br /&gt;
nSdkInstance.ggPM('49', 121);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Interruption Scenarios'''&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;window.addEventListener('beforeunload', function(event) &lt;br /&gt;
{&lt;br /&gt;
  // Only inside a midroll indicate 'stop' for the ad&lt;br /&gt;
  if (insideMidroll) {&lt;br /&gt;
    nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // Indicate 'end' for the content and 'stop' for the stream&lt;br /&gt;
  nSdkInstance.ggPM('57', playheadPosition);&lt;br /&gt;
  nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
});&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Once the DCR Tracking Code is added to Instant Articles, Nielsen will validate the implementation. Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1963</id>
		<title>DCR Italy Video Browser SDK (6.0.1)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1963"/>
		<updated>2017-11-08T10:09:39Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: /* Content Metadata */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show how to integrate the Nielsen Software Development Kit (SDK) to enable Digital Content Ratings (DCR) video measurement on browser players.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID, clientid and vcid is needed. These values are provided by Nielsen.&lt;br /&gt;
&lt;br /&gt;
The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
AppID: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The clientid is your 'parent# or companyid'&lt;br /&gt;
clientid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;XX-XXXXXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The vcid is your channel id&lt;br /&gt;
vcid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&amp;quot;xXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
* Add Static Queue Snippet&lt;br /&gt;
* Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
=== Create SDK Instance ===&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
       clientid: &amp;quot;XX-XXXXXX&amp;quot;,  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
       vcid: &amp;quot;cXX&amp;quot;,            // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
       nol_sdkDebug: &amp;quot;debug&amp;quot;   // should be deleted when going live&lt;br /&gt;
    }&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following five values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site || &amp;lt;code&amp;gt;&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || &amp;lt;code&amp;gt;&amp;quot;any string value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value has to be passed in 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value has to be passed 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Nielsen console logging. Only required for testing. in 3rd parameter object || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK601.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;, nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
* content: identify video&lt;br /&gt;
* ad: identify each ad ('''for Italy there is no need to tag ads''')&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*video – &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to content (max. 40 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || &amp;lt;code&amp;gt;YYYYMMDD hh:mm:ss&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; - full episode&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt; - non-full episode&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| subbrand || subbrand/VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| mediaURL || URL location of the content being streamed (max. 254 characters) || custom || &lt;br /&gt;
|-&lt;br /&gt;
|| hasAds || Whether the content is ad supported ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; - No Ads&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Ad Supported&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Unknown (default)&lt;br /&gt;
|| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Content Object'''&lt;br /&gt;
... with all mandatory parameters - you may ignore the optional ones.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           &amp;quot;content&amp;quot;,&lt;br /&gt;
  assetid:        &amp;quot;VID123-123456&amp;quot;,&lt;br /&gt;
  program:        &amp;quot;program name&amp;quot;,&lt;br /&gt;
  title:          &amp;quot;episode title&amp;quot;,&lt;br /&gt;
  length:         &amp;quot;1020&amp;quot;,&lt;br /&gt;
  airdate:        &amp;quot;19700101 00:00:00&amp;quot;,&lt;br /&gt;
  isfullepisode:  &amp;quot;y&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
'''Note''': for Audiweb clients there is no need to use &amp;quot;mediaURL&amp;quot;, &amp;quot;segB&amp;quot;, &amp;quot;segC&amp;quot;, &amp;quot;crossId1&amp;quot;, &amp;quot;crossId2&amp;quot; and &amp;quot;hasAds&amp;quot;. These parameters can be left out completely from structure. They are optional and not mandatory (and out of current reporting too).&lt;br /&gt;
&lt;br /&gt;
=== Ad Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Audiweb there is no need to tag ads in video stream ... you may ignore this paragraph. If there are ads in your stream, but not tagged than simply do nothing while ad is playing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of ad || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || uniqueID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Ad Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;//create ad object&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: &amp;quot;AD-1&amp;quot;,&lt;br /&gt;
  type:    &amp;quot;preroll&amp;quot;&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''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.&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is &amp;lt;code&amp;gt;ggPM()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM('event', parameter, ...);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Number !! Values to pass !! Event Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'3'&amp;lt;/code&amp;gt; || content/ad metadata object || load content metadata || Load metadata event for content. Has to be called at the very first beginning of each stream.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'5'&amp;lt;/code&amp;gt; || playhead position || content play || Call when content or ads start playing or resumes from pause. &lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'6'&amp;lt;/code&amp;gt; || playhead position || pause || Call when content or ads is pausing. Use Event 5 to resume ...&lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt; || playhead position || stop || Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'8'&amp;lt;/code&amp;gt; || playhead position from, playhead position to || seek || Call when scrubbing forward or backward with playhead position 'from' and 'to'&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt; || content/ad metadata object || load ad metadata || Call at the beginning of each ad, don’t use ‘play’ (event 5) if event 15 is used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; || playhead position || playhead position || '''VOD''': current position in seconds. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
Note: has to be called on a secondly basis.&lt;br /&gt;
For each ad the playheads starts with 0 (no Live unix timestamp for ads)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt; || playhead position || end || This event has to be called '''once''' for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Event Lifecycle ===&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;example '''without''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': if there are ads played in stream simply use a pause (event 6) when ads start playing and a play (event 5) when content start playing.&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&amp;lt;big&amp;gt; example '''with''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// Preroll&lt;br /&gt;
nSdkInstance.ggPM('15', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Midroll&lt;br /&gt;
nSdkInstance.ggPM('15', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// Postroll&lt;br /&gt;
nSdkInstance.ggPM('15', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Italy there is no need to tag ads in video stream ... ignore &amp;quot;with ads&amp;quot; example!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': Event &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling event &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when buffering occurs you have to send a event 6 (pause) and after buffering finished a 5 (play).&lt;br /&gt;
&lt;br /&gt;
'''Note''': For Ad Pods, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note''': When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Pause'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; is used for handling pause. To indicate pause, stop passing the playhead position to the SDK and send Event 6 with playhead once. When content resumes, begin sending the playhead again with the correct playhead value. Also if buffering occurs for more than 1 second you may use Event 6 (pause) to indicate that.&lt;br /&gt;
e.g. pause at 1m2s and resume after a couple of seconds:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // now send nothing to SDK until player resumes (automatically because of buffering ends or user unpauses/resumes play&lt;br /&gt;
nSdkInstance.ggPM('5', 62); // play/5 when resume occurs (when user click play or buffering ends)&lt;br /&gt;
nSdkInstance.ggPM('49', 63);&lt;br /&gt;
nSdkInstance.ggPM('49', 64);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Seek'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; is used for handling forward/backward seek. To indicate seek, send Event 8 with 'from' and 'to' playhead.&lt;br /&gt;
e.g. seek from 1m2s to 2m0s:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // use pause, because buffering will occur (to be on safe side)&lt;br /&gt;
nSdkInstance.ggPM('8', 62,120);&lt;br /&gt;
nSdkInstance.ggPM('5', 120); // play/5 when resuming&lt;br /&gt;
nSdkInstance.ggPM('49', 120);&lt;br /&gt;
nSdkInstance.ggPM('49', 121);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Interruption Scenarios'''&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;window.addEventListener('beforeunload', function(event) &lt;br /&gt;
{&lt;br /&gt;
  // Only inside a midroll indicate 'stop' for the ad&lt;br /&gt;
  if (insideMidroll) {&lt;br /&gt;
    nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // Indicate 'end' for the content and 'stop' for the stream&lt;br /&gt;
  nSdkInstance.ggPM('57', playheadPosition);&lt;br /&gt;
  nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
});&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Once the DCR Tracking Code is added to Instant Articles, Nielsen will validate the implementation. Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1933</id>
		<title>DCR Italy Video Browser SDK (6.0.1)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1933"/>
		<updated>2017-11-07T16:15:10Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show how to integrate the Nielsen Software Development Kit (SDK) to enable Digital Content Ratings (DCR) video measurement on browser players.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID, clientid and vcid is needed. These values are provided by Nielsen.&lt;br /&gt;
&lt;br /&gt;
The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
AppID: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The clientid is your 'parent# or companyid'&lt;br /&gt;
clientid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;XX-XXXXXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The vcid is your channel id&lt;br /&gt;
vcid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&amp;quot;xXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
* Add Static Queue Snippet&lt;br /&gt;
* Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
=== Create SDK Instance ===&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
       clientid: &amp;quot;XX-XXXXXX&amp;quot;,  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
       vcid: &amp;quot;cXX&amp;quot;,            // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
       nol_sdkDebug: &amp;quot;debug&amp;quot;   // should be deleted when going live&lt;br /&gt;
    }&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following five values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site || &amp;lt;code&amp;gt;&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || &amp;lt;code&amp;gt;&amp;quot;any string value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value has to be passed in 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value has to be passed 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Nielsen console logging. Only required for testing. in 3rd parameter object || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK601.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;, nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
* content: identify video&lt;br /&gt;
* ad: identify each ad ('''for Italy there is no need to tag ads''')&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*video – &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to content (max. 40 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || &amp;lt;code&amp;gt;YYYYMMDD hh:mm:ss&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; - full episode&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt; - non-full episode&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| subbrand || subbrand/VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| mediaURL || URL location of the content being streamed (max. 254 characters) || custom || &lt;br /&gt;
|-&lt;br /&gt;
|| hasAds || Whether the content is ad supported ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; - No Ads&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Ad Supported&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Unknown (default)&lt;br /&gt;
|| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Content Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           &amp;quot;content&amp;quot;,&lt;br /&gt;
  assetid:        &amp;quot;VID123-123456&amp;quot;,&lt;br /&gt;
  program:        &amp;quot;program name&amp;quot;,&lt;br /&gt;
  title:          &amp;quot;episode title&amp;quot;,&lt;br /&gt;
  length:         &amp;quot;1020&amp;quot;,&lt;br /&gt;
  airdate:        &amp;quot;19700101 00:00:00&amp;quot;,&lt;br /&gt;
  isfullepisode:  &amp;quot;y&amp;quot;,&lt;br /&gt;
  adloadtype:     &amp;quot;2&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
'''Note''': for Audiweb clients there is no need to use &amp;quot;mediaURL&amp;quot;, &amp;quot;segB&amp;quot;, &amp;quot;segC&amp;quot;, &amp;quot;crossId1&amp;quot;, &amp;quot;crossId2&amp;quot; and &amp;quot;hasAds&amp;quot;. These parameters can be left out completely from structure. They are optional and not mandatory (and out of current reporting too).&lt;br /&gt;
&lt;br /&gt;
=== Ad Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Audiweb there is no need to tag ads in video stream ... you may ignore this paragraph. If there are ads in your stream, but not tagged than simply do nothing while ad is playing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of ad || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || uniqueID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Ad Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;//create ad object&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: &amp;quot;AD-1&amp;quot;,&lt;br /&gt;
  type:    &amp;quot;preroll&amp;quot;&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''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.&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is &amp;lt;code&amp;gt;ggPM()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM('event', parameter, ...);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Number !! Values to pass !! Event Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'3'&amp;lt;/code&amp;gt; || content/ad metadata object || load content metadata || Load metadata event for content. Has to be called at the very first beginning of each stream.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'5'&amp;lt;/code&amp;gt; || playhead position || content play || Call when content or ads start playing or resumes from pause. &lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'6'&amp;lt;/code&amp;gt; || playhead position || pause || Call when content or ads is pausing. Use Event 5 to resume ...&lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt; || playhead position || stop || Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'8'&amp;lt;/code&amp;gt; || playhead position from, playhead position to || seek || Call when scrubbing forward or backward with playhead position 'from' and 'to'&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt; || content/ad metadata object || load ad metadata || Call at the beginning of each ad, don’t use ‘play’ (event 5) if event 15 is used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; || playhead position || playhead position || '''VOD''': current position in seconds. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
Note: has to be called on a secondly basis.&lt;br /&gt;
For each ad the playheads starts with 0 (no Live unix timestamp for ads)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt; || playhead position || end || This event has to be called '''once''' for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Event Lifecycle ===&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;example '''without''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': if there are ads played in stream simply use a pause (event 6) when ads start playing and a play (event 5) when content start playing.&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&amp;lt;big&amp;gt; example '''with''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// Preroll&lt;br /&gt;
nSdkInstance.ggPM('15', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Midroll&lt;br /&gt;
nSdkInstance.ggPM('15', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// Postroll&lt;br /&gt;
nSdkInstance.ggPM('15', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Italy there is no need to tag ads in video stream ... ignore &amp;quot;with ads&amp;quot; example!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': Event &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling event &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when buffering occurs you have to send a event 6 (pause) and after buffering finished a 5 (play).&lt;br /&gt;
&lt;br /&gt;
'''Note''': For Ad Pods, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note''': When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Pause'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; is used for handling pause. To indicate pause, stop passing the playhead position to the SDK and send Event 6 with playhead once. When content resumes, begin sending the playhead again with the correct playhead value. Also if buffering occurs for more than 1 second you may use Event 6 (pause) to indicate that.&lt;br /&gt;
e.g. pause at 1m2s and resume after a couple of seconds:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // now send nothing to SDK until player resumes (automatically because of buffering ends or user unpauses/resumes play&lt;br /&gt;
nSdkInstance.ggPM('5', 62); // play/5 when resume occurs (when user click play or buffering ends)&lt;br /&gt;
nSdkInstance.ggPM('49', 63);&lt;br /&gt;
nSdkInstance.ggPM('49', 64);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Seek'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; is used for handling forward/backward seek. To indicate seek, send Event 8 with 'from' and 'to' playhead.&lt;br /&gt;
e.g. seek from 1m2s to 2m0s:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // use pause, because buffering will occur (to be on safe side)&lt;br /&gt;
nSdkInstance.ggPM('8', 62,120);&lt;br /&gt;
nSdkInstance.ggPM('5', 120); // play/5 when resuming&lt;br /&gt;
nSdkInstance.ggPM('49', 120);&lt;br /&gt;
nSdkInstance.ggPM('49', 121);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Interruption Scenarios'''&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;window.addEventListener('beforeunload', function(event) &lt;br /&gt;
{&lt;br /&gt;
  // Only inside a midroll indicate 'stop' for the ad&lt;br /&gt;
  if (insideMidroll) {&lt;br /&gt;
    nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // Indicate 'end' for the content and 'stop' for the stream&lt;br /&gt;
  nSdkInstance.ggPM('57', playheadPosition);&lt;br /&gt;
  nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
});&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Once the DCR Tracking Code is added to Instant Articles, Nielsen will validate the implementation. Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1928</id>
		<title>DCR Italy Video Browser SDK (6.0.1)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1928"/>
		<updated>2017-11-07T12:13:07Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show how to integrate the Nielsen Software Development Kit (SDK) to enable Digital Content Ratings (DCR) video measurement on browser players.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID, clientid and vcid is needed. These values are provided by Nielsen.&lt;br /&gt;
&lt;br /&gt;
The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
AppID: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The clientid is your 'parent# or companyid'&lt;br /&gt;
clientid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;XX-XXXXXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The vcid is your channel id&lt;br /&gt;
vcid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&amp;quot;xXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
* Add Static Queue Snippet&lt;br /&gt;
* Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
=== Create SDK Instance ===&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
       clientid: &amp;quot;XX-XXXXXX&amp;quot;,  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
       vcid: &amp;quot;cXX&amp;quot;,            // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
       nol_sdkDebug: &amp;quot;debug&amp;quot;   // should be deleted when going live&lt;br /&gt;
    }&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following three values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site || &amp;lt;code&amp;gt;&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || &amp;lt;code&amp;gt;&amp;quot;any string value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value has to be passed in 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value has to be passed 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Nielsen console logging. Only required for testing. in 3rd parameter object || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK601.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;, nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
* content: identify video&lt;br /&gt;
* ad: identify each ad ('''for Italy there is no need to tag ads''')&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*video – &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to content (max. 40 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || &amp;lt;code&amp;gt;YYYYMMDD hh:mm:ss&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; - full episode&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt; - non-full episode&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| subbrand || subbrand/VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| mediaURL || URL location of the content being streamed (max. 254 characters) || custom || &lt;br /&gt;
|-&lt;br /&gt;
|| hasAds || Whether the content is ad supported ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; - No Ads&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Ad Supported&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Unknown (default)&lt;br /&gt;
|| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Content Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           &amp;quot;content&amp;quot;,&lt;br /&gt;
  assetid:        &amp;quot;VID123-123456&amp;quot;,&lt;br /&gt;
  program:        &amp;quot;program name&amp;quot;,&lt;br /&gt;
  title:          &amp;quot;episode title&amp;quot;,&lt;br /&gt;
  length:         &amp;quot;1020&amp;quot;,&lt;br /&gt;
  airdate:        &amp;quot;19700101 00:00:00&amp;quot;,&lt;br /&gt;
  isfullepisode:  &amp;quot;y&amp;quot;,&lt;br /&gt;
  adloadtype:     &amp;quot;2&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
'''Note''': for Audiweb clients there is no need to use &amp;quot;mediaURL&amp;quot;, &amp;quot;segB&amp;quot;, &amp;quot;segC&amp;quot;, &amp;quot;crossId1&amp;quot;, &amp;quot;crossId2&amp;quot; and &amp;quot;hasAds&amp;quot;. These parameters can be left out completely from structure. They are optional and not mandatory (and out of current reporting too).&lt;br /&gt;
&lt;br /&gt;
=== Ad Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Audiweb there is no need to tag ads in video stream ... you may ignore this paragraph. If there are ads in your stream, but not tagged than simply do nothing while ad is playing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of ad || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || uniqueID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Ad Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;//create ad object&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: &amp;quot;AD-1&amp;quot;,&lt;br /&gt;
  type:    &amp;quot;preroll&amp;quot;&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''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.&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is &amp;lt;code&amp;gt;ggPM()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM('event', parameter, ...);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Number !! Values to pass !! Event Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'3'&amp;lt;/code&amp;gt; || content/ad metadata object || load content metadata || Load metadata event for content. Has to be called at the very first beginning of each stream.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'5'&amp;lt;/code&amp;gt; || playhead position || content play || Call when content or ads start playing or resumes from pause. &lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'6'&amp;lt;/code&amp;gt; || playhead position || pause || Call when content or ads is pausing. Use Event 5 to resume ...&lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt; || playhead position || stop || Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'8'&amp;lt;/code&amp;gt; || playhead position from, playhead position to || seek || Call when scrubbing forward or backward with playhead position 'from' and 'to'&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt; || content/ad metadata object || load ad metadata || Call at the beginning of each ad, don’t use ‘play’ (event 5) if event 15 is used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; || playhead position || playhead position || '''VOD''': current position in seconds. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
Note: has to be called on a secondly basis.&lt;br /&gt;
For each ad the playheads starts with 0 (no Live unix timestamp for ads)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt; || playhead position || end || This event has to be called '''once''' for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Event Lifecycle ===&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;example '''without''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': if there are ads played in stream simply use a pause (event 6) when ads start playing and a play (event 5) when content start playing.&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&amp;lt;big&amp;gt; example '''with''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// Preroll&lt;br /&gt;
nSdkInstance.ggPM('15', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Midroll&lt;br /&gt;
nSdkInstance.ggPM('15', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// Postroll&lt;br /&gt;
nSdkInstance.ggPM('15', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Italy there is no need to tag ads in video stream ... ignore &amp;quot;with ads&amp;quot; example!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': Event &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling event &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when buffering occurs you have to send a event 6 (pause) and after buffering finished a 5 (play).&lt;br /&gt;
&lt;br /&gt;
'''Note''': For Ad Pods, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note''': When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Pause'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; is used for handling pause. To indicate pause, stop passing the playhead position to the SDK and send Event 6 with playhead once. When content resumes, begin sending the playhead again with the correct playhead value. Also if buffering occurs for more than 1 second you may use Event 6 (pause) to indicate that.&lt;br /&gt;
e.g. pause at 1m2s and resume after a couple of seconds:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // now send nothing to SDK until player resumes (automatically because of buffering ends or user unpauses/resumes play&lt;br /&gt;
nSdkInstance.ggPM('5', 62); // play/5 when resume occurs (when user click play or buffering ends)&lt;br /&gt;
nSdkInstance.ggPM('49', 63);&lt;br /&gt;
nSdkInstance.ggPM('49', 64);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Seek'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; is used for handling forward/backward seek. To indicate seek, send Event 8 with 'from' and 'to' playhead.&lt;br /&gt;
e.g. seek from 1m2s to 2m0s:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // use pause, because buffering will occur (to be on safe side)&lt;br /&gt;
nSdkInstance.ggPM('8', 62,120);&lt;br /&gt;
nSdkInstance.ggPM('5', 120); // play/5 when resuming&lt;br /&gt;
nSdkInstance.ggPM('49', 120);&lt;br /&gt;
nSdkInstance.ggPM('49', 121);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Interruption Scenarios'''&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;window.addEventListener('beforeunload', function(event) &lt;br /&gt;
{&lt;br /&gt;
  // Only inside a midroll indicate 'stop' for the ad&lt;br /&gt;
  if (insideMidroll) {&lt;br /&gt;
    nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // Indicate 'end' for the content and 'stop' for the stream&lt;br /&gt;
  nSdkInstance.ggPM('57', playheadPosition);&lt;br /&gt;
  nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
});&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Once the DCR Tracking Code is added to Instant Articles, Nielsen will validate the implementation. Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1927</id>
		<title>DCR Italy Video Browser SDK (6.0.1)</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=DCR_Italy_Video_Browser_SDK_(6.0.1)&amp;diff=1927"/>
		<updated>2017-11-07T12:11:54Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Breadcrumb|}} {{Breadcrumb|Digital}} {{Breadcrumb|International}}  {{CurrentBreadcrumb}}&lt;br /&gt;
[[Category:Digital]]&lt;br /&gt;
&lt;br /&gt;
This guide will show how to integrate the Nielsen Software Development Kit (SDK) to enable Digital Content Ratings (DCR) video measurement on browser players.&lt;br /&gt;
&lt;br /&gt;
== Prerequisites ==&lt;br /&gt;
To get started, an App ID, clientid and vcid is needed. These values are provided by Nielsen.&lt;br /&gt;
&lt;br /&gt;
The App ID is a unique ID assigned to the player/site/app. This will be provided upon starting the integration.&lt;br /&gt;
AppID: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;PXXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The clientid is your 'parent# or companyid'&lt;br /&gt;
clientid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;XX-XXXXXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The vcid is your channel id&lt;br /&gt;
vcid: &amp;lt;syntaxhighlight lang=&amp;quot;console&amp;quot;&amp;gt;&amp;quot;xXX&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;  // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
&lt;br /&gt;
== Configure SDK ==&lt;br /&gt;
There are two steps required for configuring the SDK:&lt;br /&gt;
* Add Static Queue Snippet&lt;br /&gt;
* Create SDK Instance&lt;br /&gt;
&lt;br /&gt;
=== Add Static Queue Snippet ===&lt;br /&gt;
&lt;br /&gt;
Add the following script tag to the website:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script&amp;gt;&lt;br /&gt;
!function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The static queue snippet allows the SDK APIs to be called while the actual SDK and configuration file are still being downloaded. As the queue can capture all API calls before the download completes, there is no wait time. Once the SDK is available, the API calls will transition from directing to the queue to the SDK seamlessly.&lt;br /&gt;
&lt;br /&gt;
=== Create SDK Instance ===&lt;br /&gt;
&lt;br /&gt;
To initialize the SDK, create an SDK instance by making the initialization call:&lt;br /&gt;
&lt;br /&gt;
'''Initialization API Call'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;NOLBUNDLE.nlsQ(&amp;quot;&amp;lt;apid&amp;gt;&amp;quot;, &amp;quot;&amp;lt;instanceName&amp;gt;&amp;quot;,&lt;br /&gt;
    {&lt;br /&gt;
       clientid: &amp;quot;XX-XXXXXX&amp;quot;,  // eg. &amp;quot;it-123456&amp;quot;&lt;br /&gt;
       vcid: &amp;quot;cXX&amp;quot;,            // eg. &amp;quot;c01&amp;quot;&lt;br /&gt;
       nol_sdkDebug: &amp;quot;debug&amp;quot;   // should be deleted when going live&lt;br /&gt;
    }&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When creating an instance, pass the following three values:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Parameter !! Description !! Values&lt;br /&gt;
|-&lt;br /&gt;
| apid || Unique ID assigned to player/site || &amp;lt;code&amp;gt;&amp;quot;PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| instanceName || Name of SDK instance || &amp;lt;code&amp;gt;&amp;quot;any string value&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value has to be passed in 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| vcid || VCID value has to be passed 3rd parameter object || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| nol_sdkDebug || Enables Nielsen console logging. Only required for testing. in 3rd parameter object || &amp;lt;code&amp;gt;{nol_sdkDebug: &amp;quot;debug&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When the initialization call is made, a unique static configuration file, &amp;lt;code&amp;gt;&amp;lt;apid&amp;gt;.js&amp;lt;/code&amp;gt;, will be downloaded based on the &amp;lt;code&amp;gt;apid&amp;lt;/code&amp;gt; and will be cached on the user’s browser.&lt;br /&gt;
&lt;br /&gt;
Once the configuration is downloaded, the SDK itself will be downloaded and initialized. All SDK modules are included in one file: “nlsSDK601.bundle.min.js”.&lt;br /&gt;
&lt;br /&gt;
=== Example SDK Configuration ===&lt;br /&gt;
&lt;br /&gt;
The configuration should include the Static Queue Snippet and an SDK Instance for an unique App ID as shown in the example:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
  // Add Static Queue Snippet&lt;br /&gt;
 !function(t,n)&lt;br /&gt;
{&lt;br /&gt;
  t[n]=t[n]||&lt;br /&gt;
  {&lt;br /&gt;
    nlsQ:function(e,o,c,r,s,i)&lt;br /&gt;
    {&lt;br /&gt;
     return s=t.document,&lt;br /&gt;
     r=s.createElement(&amp;quot;script&amp;quot;),&lt;br /&gt;
     r.async=1,&lt;br /&gt;
     r.src=(&amp;quot;http:&amp;quot;===t.location.protocol?&amp;quot;http:&amp;quot;:&amp;quot;https:&amp;quot;)+&amp;quot;//cdn-gl.imrworldwide.com/conf/&amp;quot;+e+&amp;quot;.js#name=&amp;quot;+o+&amp;quot;&amp;amp;ns=&amp;quot;+n,&lt;br /&gt;
     i=s.getElementsByTagName(&amp;quot;script&amp;quot;)[0],&lt;br /&gt;
     i.parentNode.insertBefore(r,i),&lt;br /&gt;
     t[n][o]=t[n][o]||{g:c||{},&lt;br /&gt;
     ggPM:function(e,c,r,s,i){(t[n][o].q=t[n][o].q||[]).push([e,c,r,s,i])}},t[n][o]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
(window,&amp;quot;NOLBUNDLE&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
  // Created SDK Instance&lt;br /&gt;
  var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;, nol_sdkDebug: &amp;quot;DEBUG&amp;quot;});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Create Metadata Objects ==&lt;br /&gt;
There are two types of asset metadata:&lt;br /&gt;
* content: identify video&lt;br /&gt;
* ad: identify each ad ('''for Italy there is no need to tag ads''')&lt;br /&gt;
The metadata received for each asset is used for classification and reporting.&lt;br /&gt;
&lt;br /&gt;
Metadata can be passed through key-values using the Nielsen reserved keys. User will need to set up content and ad objects with the required Nielsen keys as shown in the sample code below.&lt;br /&gt;
&lt;br /&gt;
=== Content Metadata ===&lt;br /&gt;
&lt;br /&gt;
Content metadata should remain constant throughout the completion of an episode / clip including the ads play.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Key !! Description !! Values !! Required?&lt;br /&gt;
|-&lt;br /&gt;
| type ||&lt;br /&gt;
Type of measurement:&lt;br /&gt;
*video – &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;content&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || Unique ID assigned to content (max. 40 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| program || Program name (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| title || Episode title (max. 254 characters) || custom || ✓&lt;br /&gt;
|-&lt;br /&gt;
| length || Length of content in seconds for VOD. The estimated content length has to be passed for live content. || &amp;lt;code&amp;gt;seconds&amp;lt;/code&amp;gt; (86400 for live stream) || ✓&lt;br /&gt;
|-&lt;br /&gt;
| airdate || Original (local) air date and time (hh:mm:ss as 24h time stamp); if not known set it to eg. &amp;quot;19700101 00:00:00&amp;quot; || &amp;lt;code&amp;gt;YYYYMMDD hh:mm:ss&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| isfullepisode || Full episode flag ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;y&amp;quot;&amp;lt;/code&amp;gt; - full episode&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;n&amp;quot;&amp;lt;/code&amp;gt; - non-full episode&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| adloadtype ||&lt;br /&gt;
Type of ad load:&lt;br /&gt;
#Linear - matches TV ad load&lt;br /&gt;
#Dynamic - Dynamic Ad Insertion (DAI)&lt;br /&gt;
|| &amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Linear&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Dynamic&lt;br /&gt;
|| ✓&lt;br /&gt;
|-&lt;br /&gt;
| clientid || Brand value is automatically populated through the App ID provided. The value passed here will override the default value. (e.g. Multiple brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| subbrand || subbrand/VCID value is automatically populated through the App ID provided. This value passed here will override the default value. (e.g. Multiple Sub-brands in App) || Nielsen provided || &lt;br /&gt;
|-&lt;br /&gt;
| mediaURL || URL location of the content being streamed (max. 254 characters) || custom || &lt;br /&gt;
|-&lt;br /&gt;
|| hasAds || Whether the content is ad supported ||&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/code&amp;gt; - No Ads&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;1&amp;quot;&amp;lt;/code&amp;gt; - Ad Supported&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;2&amp;quot;&amp;lt;/code&amp;gt; - Unknown (default)&lt;br /&gt;
|| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Content Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
//create content object&lt;br /&gt;
var contentMetadataObject =&lt;br /&gt;
{  &lt;br /&gt;
  type:           &amp;quot;content&amp;quot;,&lt;br /&gt;
  assetid:        &amp;quot;VID123-123456&amp;quot;,&lt;br /&gt;
  program:        &amp;quot;program name&amp;quot;,&lt;br /&gt;
  title:          &amp;quot;episode title&amp;quot;,&lt;br /&gt;
  length:         &amp;quot;1020&amp;quot;,&lt;br /&gt;
  airdate:        &amp;quot;19700101 00:00:00&amp;quot;,&lt;br /&gt;
  isfullepisode:  &amp;quot;y&amp;quot;,&lt;br /&gt;
  adloadtype:     &amp;quot;2&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': all parameters should be provided as strings (also length)&lt;br /&gt;
&lt;br /&gt;
'''Note''': for Audiweb clients there is no need to use &amp;quot;mediaURL&amp;quot;, &amp;quot;segB&amp;quot;, &amp;quot;segC&amp;quot;, &amp;quot;crossId1&amp;quot;, &amp;quot;crossId2&amp;quot; and &amp;quot;hasAds&amp;quot;. These parameters can be left out completely from structure. They are optional and not mandatory (and out of current reporting too).&lt;br /&gt;
&lt;br /&gt;
=== Ad Object ===&lt;br /&gt;
The ad metadata should be passed for each individual ad.&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Audiweb there is no need to tag ads in video stream ... you may ignore this paragraph. If there are ads in your stream, but not tagged than simply do nothing while ad is playing.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Keys !! Description !! Values !! Required&lt;br /&gt;
|-&lt;br /&gt;
| type || type of ad || &amp;lt;code&amp;gt;&amp;quot;preroll&amp;quot;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;midroll&amp;quot;&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;&amp;quot;postroll&amp;quot;&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|-&lt;br /&gt;
| assetid || uniqueID assigned to ad || &amp;lt;code&amp;gt;custom&amp;lt;/code&amp;gt; || ✓&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Example Ad Object'''&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;//create ad object&lt;br /&gt;
var adMetadataObject = &lt;br /&gt;
{  &lt;br /&gt;
  assetid: &amp;quot;AD-1&amp;quot;,&lt;br /&gt;
  type:    &amp;quot;preroll&amp;quot;&lt;br /&gt;
};&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''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.&lt;br /&gt;
&lt;br /&gt;
== Call Nielsen APIs ==&lt;br /&gt;
The method for calling events is &amp;lt;code&amp;gt;ggPM()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;nSdkInstance.ggPM('event', parameter, ...);&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Events ===&lt;br /&gt;
The events are included in the table below:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Event Number !! Values to pass !! Event Name || Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'3'&amp;lt;/code&amp;gt; || content/ad metadata object || load content metadata || Load metadata event for content. Has to be called at the very first beginning of each stream.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'5'&amp;lt;/code&amp;gt; || playhead position || content play || Call when content or ads start playing or resumes from pause. &lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'6'&amp;lt;/code&amp;gt; || playhead position || pause || Call when content or ads is pausing. Use Event 5 to resume ...&lt;br /&gt;
'''VOD''' (or ad): The playhead position must be passed. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt; || playhead position || stop || Call when ads complete playing and at the very end of the stream. The playhead position must be passed when calling stop&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'8'&amp;lt;/code&amp;gt; || playhead position from, playhead position to || seek || Call when scrubbing forward or backward with playhead position 'from' and 'to'&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt; || content/ad metadata object || load ad metadata || Call at the beginning of each ad, don’t use ‘play’ (event 5) if event 15 is used&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; || playhead position || playhead position || '''VOD''': current position in seconds. &lt;br /&gt;
'''Live''': current unix timestamp (seconds since January 1st 1970).&lt;br /&gt;
Note: has to be called on a secondly basis.&lt;br /&gt;
For each ad the playheads starts with 0 (no Live unix timestamp for ads)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt; || playhead position || end || This event has to be called '''once''' for the current video asset at the end of the playback.&lt;br /&gt;
At the end of the content stream, if the user switches to another piece of content or when the browser is refreshed or closed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== SDK Event Lifecycle ===&lt;br /&gt;
The sample event lifecycle can be used as a reference for identifying the order for calling events.&lt;br /&gt;
&lt;br /&gt;
{{Examples|&lt;br /&gt;
without Ads|&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;example '''without''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream&lt;br /&gt;
&lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Note''': if there are ads played in stream simply use a pause (event 6) when ads start playing and a play (event 5) when content start playing.&lt;br /&gt;
&lt;br /&gt;
|with Ads=&lt;br /&gt;
&amp;lt;big&amp;gt; example '''with''' ads:&amp;lt;/big&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// Start of stream&lt;br /&gt;
nSdkInstance.ggPM('3', contentMetadataObject); // must be called as start of stream (even if 1st asset is preroll)&lt;br /&gt;
 &lt;br /&gt;
// Preroll&lt;br /&gt;
nSdkInstance.ggPM('15', prerollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from 0 for the first segment (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Midroll&lt;br /&gt;
nSdkInstance.ggPM('15', midrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// Content&lt;br /&gt;
nSdkInstance.ggPM('5',  contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition); // must be fired every second with playhead starting from where it left off before mid-roll (or with seconds since 1970-01-01 00:00:00 in case of livestream)&lt;br /&gt;
... /*** pass playheads every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', contentPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('6',  contentPlayheadPosition);  // pause is also needed for legacy reasons before event 57&lt;br /&gt;
nSdkInstance.ggPM('57', contentPlayheadPosition);  // has to be called here at the end of the content only once&lt;br /&gt;
 &lt;br /&gt;
// Postroll&lt;br /&gt;
nSdkInstance.ggPM('15', postrollMetadataObject);&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition); // must be fired every second with playhead starting from 0&lt;br /&gt;
... /*** pass playhead every second ***/&lt;br /&gt;
nSdkInstance.ggPM('49', individualAdPlayheadPosition);&lt;br /&gt;
nSdkInstance.ggPM('7',  individualAdPlayheadPosition);&lt;br /&gt;
 &lt;br /&gt;
// End of Stream&lt;br /&gt;
nSdkInstance.ggPM('7',  contentPlayheadPosition); // must be called as indicator for end-of-stream&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Attention:''' for Italy there is no need to tag ads in video stream ... ignore 2nd example!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Note''': Event &amp;lt;code&amp;gt;'49'&amp;lt;/code&amp;gt; is used for calculating duration and must be passed every second. The final playhead position must be sent for the current asset being played before calling event &amp;lt;code&amp;gt;'7'&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;'57'&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;'15'&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Note''': when buffering occurs you have to send a event 6 (pause) and after buffering finished a 5 (play).&lt;br /&gt;
&lt;br /&gt;
'''Note''': For Ad Pods, events must be called for each individual Ad. Each Ad playhead position should begin at ‘0’ when ad starts.&lt;br /&gt;
&lt;br /&gt;
'''Note''': When content has resumed following an ad break, the playhead position update must continue where previous content segment left off. The playhead position should be passed as a rounded number with no decimals.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Pause'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;6&amp;lt;/code&amp;gt; is used for handling pause. To indicate pause, stop passing the playhead position to the SDK and send Event 6 with playhead once. When content resumes, begin sending the playhead again with the correct playhead value. Also if buffering occurs for more than 1 second you may use Event 6 (pause) to indicate that.&lt;br /&gt;
e.g. pause at 1m2s and resume after a couple of seconds:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // now send nothing to SDK until player resumes (automatically because of buffering ends or user unpauses/resumes play&lt;br /&gt;
nSdkInstance.ggPM('5', 62); // play/5 when resume occurs (when user click play or buffering ends)&lt;br /&gt;
nSdkInstance.ggPM('49', 63);&lt;br /&gt;
nSdkInstance.ggPM('49', 64);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Handling Seek'''&lt;br /&gt;
The event &amp;lt;code&amp;gt;8&amp;lt;/code&amp;gt; is used for handling forward/backward seek. To indicate seek, send Event 8 with 'from' and 'to' playhead.&lt;br /&gt;
e.g. seek from 1m2s to 2m0s:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
nSdkInstance.ggPM('49', 61);&lt;br /&gt;
nSdkInstance.ggPM('49', 62);&lt;br /&gt;
nSdkInstance.ggPM('6', 62); // use pause, because buffering will occur (to be on safe side)&lt;br /&gt;
nSdkInstance.ggPM('8', 62,120);&lt;br /&gt;
nSdkInstance.ggPM('5', 120); // play/5 when resuming&lt;br /&gt;
nSdkInstance.ggPM('49', 120);&lt;br /&gt;
nSdkInstance.ggPM('49', 121);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Interruption Scenarios'''&lt;br /&gt;
The following possible browser interruption scenarios must be handled:&lt;br /&gt;
* Browser/Tab close&lt;br /&gt;
* Leaving the page to another destination&lt;br /&gt;
* Pressing the stop button&lt;br /&gt;
There are many cases where the player itself has the ability to detect such situations. If not, these interruption scenarios can be handled through JavaScript. The events that are called will depend on the asset being played (e.g. midroll vs. content).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;window.addEventListener('beforeunload', function(event) &lt;br /&gt;
{&lt;br /&gt;
  // Only inside a midroll indicate 'stop' for the ad&lt;br /&gt;
  if (insideMidroll) {&lt;br /&gt;
    nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  // Indicate 'end' for the content and 'stop' for the stream&lt;br /&gt;
  nSdkInstance.ggPM('57', playheadPosition);&lt;br /&gt;
  nSdkInstance.ggPM('7', playheadPosition);&lt;br /&gt;
});&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Note''': User may need to add code to support specific browser versions (e.g. older versions of Internet Explorer).&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Opt-Out ==&lt;br /&gt;
The site must provide a means for the user to opt-out of, or opt back into, Nielsen Measurement. A user can opt-out if they would prefer not to participate in any Nielsen online measurement research. To implement the opt-out option, include the following two items in your privacy policy.&lt;br /&gt;
* A notice that the player includes proprietary measurement software that allows users to contribute to market research (such as Nielsen TV Ratings).&lt;br /&gt;
* A link to the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.&lt;br /&gt;
On the Nielsen Digital Measurement Privacy Policy page, users can click Choices to read more detailed information about the measurement software, learn about their options with regard to Nielsen measurement, and, if they do not want to participate in Nielsen online measurement, click a link to receive an opt-out cookie.&lt;br /&gt;
&lt;br /&gt;
The following paragraph is a template for an opt-out statement.&lt;br /&gt;
&lt;br /&gt;
''The properties may feature Nielsen proprietary measurement software, which will allow users to contribute to market research, such as Nielsen TV Ratings. To learn more about the information that Nielsen software may collect and your choices with regard to it, please see the Nielsen Digital Measurement Privacy Policy at https://priv-policy.imrworldwide.com/priv/browser/it/it/optout.html.''&lt;br /&gt;
&lt;br /&gt;
'''Opt Back In'''&lt;br /&gt;
&lt;br /&gt;
Once users have opted-out, they can choose to opt back into Nielsen Measurement at anytime by selecting the opt back in link on the Nielsen Digital Privacy Policy page. When a user selects the link, their opt-out cookie will be deleted and they will be able to be measured.&lt;br /&gt;
&lt;br /&gt;
== Going Live ==&lt;br /&gt;
Once the DCR Tracking Code is added to Instant Articles, Nielsen will validate the implementation. Following Nielsen testing, users need to make a couple of updates to the initialization call to ensure that the site is being measured properly.&lt;br /&gt;
# '''Debug Logging''': Disable logging by deleting &amp;lt;code&amp;gt;{nol_sdkDebug: 'DEBUG'}&amp;lt;/code&amp;gt; from initialization call.&lt;br /&gt;
#* '''Example Production Initialization Call''' - Refer to the production initialization call below:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;var nSdkInstance = NOLBUNDLE.nlsQ(&amp;quot;P14273221-CF5C-46BF-A832-994AEFB73AA4&amp;quot;,&amp;quot;myPlayerName&amp;quot;, {clientid: &amp;quot;it-123456&amp;quot;, vcid: &amp;quot;c01&amp;quot;});&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=Template:Examples&amp;diff=1926</id>
		<title>Template:Examples</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=Template:Examples&amp;diff=1926"/>
		<updated>2017-11-07T12:06:22Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;section-container auto&amp;quot; data-section&amp;gt;&lt;br /&gt;
{{#if: {{{1|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;{{{1}}}&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{2}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
 {{#if: {{{without Ads|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;without Ads&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{without Ads}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
 {{#if: {{{with Ads|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;with Ads&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{with Ads}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=Template:Examples&amp;diff=1925</id>
		<title>Template:Examples</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=Template:Examples&amp;diff=1925"/>
		<updated>2017-11-07T11:42:38Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;section-container auto&amp;quot; data-section&amp;gt;&lt;br /&gt;
{{#if: {{{1|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;{{{1}}}&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{2}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
 {{#if: {{{withoutAds|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;without Ads&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{withoutAds}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
 {{#if: {{{withAds|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;with Ads&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{withAds}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=Template:Examples&amp;diff=1924</id>
		<title>Template:Examples</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=Template:Examples&amp;diff=1924"/>
		<updated>2017-11-07T11:40:15Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;section-container auto&amp;quot; data-section&amp;gt;&lt;br /&gt;
{{#if: {{{1|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;{{{1}}}&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{2}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
 {{#if: {{{withoutAds|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;without Ads&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{without Ads}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
 {{#if: {{{withAds|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;with Ads&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{with Ads}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=Template:Examples&amp;diff=1923</id>
		<title>Template:Examples</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=Template:Examples&amp;diff=1923"/>
		<updated>2017-11-07T11:38:18Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;section-container auto&amp;quot; data-section&amp;gt;&lt;br /&gt;
{{#if: {{{1|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;{{{1}}}&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{2}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
 {{#if: {{{withoutAds|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;without Ads&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{withoutAds}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
 {{#if: {{{withAds|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;with Ads&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{withAds}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
	<entry>
		<id>https://engineeringportal.nielsen.com/w/index.php?title=Template:Examples&amp;diff=1922</id>
		<title>Template:Examples</title>
		<link rel="alternate" type="text/html" href="https://engineeringportal.nielsen.com/w/index.php?title=Template:Examples&amp;diff=1922"/>
		<updated>2017-11-07T11:35:50Z</updated>

		<summary type="html">&lt;p&gt;NielsSedat: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;section-container auto&amp;quot; data-section&amp;gt;&lt;br /&gt;
{{#if: {{{1|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;{{{1}}}&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{2}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
 {{#if: {{{withoutAds|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;without Ads&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{without Ads}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
 {{#if: {{{withAds|}}} | &amp;lt;div class=&amp;quot;section&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;p class=&amp;quot;title&amp;quot; data-section-title&amp;gt;with Ads&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;div class=&amp;quot;content&amp;quot; data-section-content&amp;gt;&lt;br /&gt;
{{{with Ads}}}&lt;br /&gt;
    &amp;lt;/div&amp;gt;&lt;br /&gt;
  &amp;lt;/div&amp;gt; | }}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>NielsSedat</name></author>
	</entry>
</feed>