Digital Pre-Certification Checklist App SDK: Difference between revisions

From Engineering Client Portal

No edit summary
No edit summary
 
(11 intermediate revisions by 4 users not shown)
Line 2: Line 2:
[[Category:Digital]]
[[Category:Digital]]


== Pre-certification Checklist - VOD with Ads ==
== Pre-Certification Checklist ==
Before starting the certification process, please verify the following steps have been completed.
Before starting the certification process, please verify the following steps have been completed.
* Your Client Service representative should have already discussed a reporting hierarchy with you -- along with a Parent, Brand, and Sub-brand/Channel
* Your Client Service representative should have already discussed a reporting hierarchy with you -- along with a Parent, Brand, and Sub-brand/Channel
* Your Technical Account Manager should have:
* Your Integration Engineer should have:
** provided you with an AppID
** provided you with an AppID
** informed you of our Opt-Out requirement for your App/Play Store description
** informed you of our Opt-Out requirement for a WebView inside your apps
** informed you of our Opt-Out requirement for a WebView inside your apps
* Retrieving AppSDK logs
* Retrieving AppSDK logs
** ‘nol_devDebug’ : 'DEBUG' should be present in initialization call (see below)
** 'nol_devDebug' : 'DEBUG' should be present in initialization call (see below)
** Android: use adb logcat (note: requires Android Studio)
** Android: use adb logcat (note: requires Android Studio)
** iOS: idevicesyslog (note: requires XCode)
** iOS: idevicesyslog (note: requires XCode)


== Initialization ==
== Test Cases ==
The following lists the test cases along with expected results:
 
 
<blockquote>'''Note:''' Due to the variable and unique nature of each application,  there may be additional testing required by Nielsen that is not listed here.  These tests are completed to ensure the quality of data collected.  Please speak with your account manager if you have any questions.</blockquote>
 
=== Initialization ===
The first step in the Certification process is to ensure that the Nielsen SDK is initializing at app startup, and that the global metadata values are present.
The first step in the Certification process is to ensure that the Nielsen SDK is initializing at app startup, and that the global metadata values are present.
{| class="wikitable"
{| class="wikitable"
Line 29: Line 34:
|}
|}


'''iOS Example'''
'''iOS Example:'''
<syntaxhighlight lang="objective-c">NSDictionary* appInformation = @
<syntaxhighlight lang="objective-c">NSDictionary* appInformation = @
{ // AppID is Nielsen-supplied
{ // AppID is Nielsen-supplied
Line 38: Line 43:
}</syntaxhighlight>
}</syntaxhighlight>


'''Android Example'''
'''Android Example:'''
<syntaxhighlight lang="java">JSONObject appSdkConfig = new JSONObject()
<syntaxhighlight lang="java">JSONObject appSdkConfig = new JSONObject()
           .put("appid", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
           .put("appid", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
           .put("appname", "Sample App Name")
           .put("appname", "Sample App Name")
           .put("appversion","2.0")
           .put("appversion","2.0")
           .put("nol_devDebug”, "DEBUG"); // required for testing only
           .put("nol_devDebug", "DEBUG"); // required for testing only
// Pass appSdkConfig to the AppSdk constructor
// Pass appSdkConfig to the AppSdk constructor
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);</syntaxhighlight>
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);</syntaxhighlight>


== Test Cases ==
 
The following lists the test cases along with the Expected results:
=== Config Ping ===
Confirm that SDK initialization is occurring at app start-up by presence of configuration ping.
 
Sample Ping:
<code> <nowiki>https://cdn-gl.imrworldwide.com/conf/PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.json?devtypid=iPhone8,2&devid=12b9377cbe7e5c94e8a70d9d23929523d14afa954793130f8a3959c7b849aca8
&devname=My%20iPhone&osver=iOS13.6&sysname=iOS&bid=com.nielsen.com.test.config </nowiki></code>
 
{| class="wikitable"
|-
! App ID !! Description
|-
| PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX || Should be your App ID for the integration
|}
 
=== SDK Event Sequence Check ===
 
==== SDK DCR Video Events ====
 
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 for DCR.
{| class="wikitable"
{| class="wikitable"
|-
|-
! Test Case !! Param !! Expected Result !! Pass/Fail
! Type !! Sample Code !! Description
|-
| rowspan="2" | Start of stream || <code>mAppSdk.play(); </code> || // stream starts
|-
| <code>mAppSdk.loadMetadata(contentMetaDataObject);</code> || // contentMetadataObject contains the JSON metadata for the content being played
|-
| rowspan="3" | Preroll || <code>mAppSdk.loadMetadata(prerollMetadataObject);</code> || // prerollMetadataObject contains the JSON metadata for the preroll ad
|-
| <code>mAppSdk.playheadPosition(playheadPosition);</code> || // position is position of the playhead while the preroll ad is being played
|-
| <code>mAppSdk.stop();</code> || // Call stop after preroll occurs
|-
| rowspan="2" | Content || <code>mAppSdk.loadMetadata(contentMetaDataObject);</code> || // contentMetadataObject contains the JSON metadata for the content being played
|-
| <code>mAppSdk.playheadPosition(playheadPosition);</code> || // position is position of the playhead while the content is being played
|-
| rowspan="3" | Midroll || <code>mAppSdk.loadMetadata(midrollMetaDataObject);</code> || // midrollMetadataObject contains the JSON metadata for the midroll ad
|-
| <code>mAppSdk.playheadPosition(playheadPosition);</code> || // position is position of the playhead while the midroll ad is being played
|-
| <code>mAppSdk.stop();</code> || // Call stop after midroll occurs
|-
| rowspan="2" | Content Resumes || <code>mAppSdk.loadMetadata(contentMetaDataObject);</code> || // contentMetadataObject contains the JSON metadata for the content being played
|-
| <code>mAppSdk.playheadPosition(playheadPosition);</code> || // position is position of the playhead while the content is being played
|-
|-
| SDK Initialized || <code>appid</code> || Correct app id ||
| End of Stream || <code>mAppSdk.end();</code> || // Call end() at the end of content
|-
|-
| || <code>appname</code> || Player name ||
| rowspan="3" | Postroll || <code>mAppSdk.loadMetadata(postrollMetaDataObject);</code> || // postrollMetadataObject contains the JSON metadata for the postroll ad
|-
|-
|  || <code>appversion</code> || Correct build ||
| <code>mAppSdk.playheadPosition(playheadPosition);</code> || // position is position of the playhead while the postroll ad is being played
|-
|-
|  || <code>nol_devDebug</code> || <code>'DEBUG</code> ||
| <code>mAppSdk.stop();</code> || // Call stop after postroll occurs
|}
|}


=== play() ===
<blockquote> Note: Each Ad playhead should 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. </blockquote>
* The <code>play()</code> call is required only once per viewing session (until app is killed)
 
* Called just before playback commences for first piece of content
===== play() =====
* Call at start of each new stream before playback commences
{| class="wikitable"
{| class="wikitable"
|-
|-
Line 72: Line 120:
|}
|}


=== loadMetadata() - Content ===
===== loadMetadata() for DCR Content =====
* Called at beginning of content, or when resuming content from interruption
* Called at beginning of content, or when resuming content from interruption or ad
{| class="wikitable"
{| class="wikitable"
|-
|-
! Test !! Param !! Example Value !! Accepted Values !! Pass/Fail
! Test !! Param !! Example Value !! Accepted Values !! Ping Parameter !! Pass/Fail
|-
|-
| loadMetadata || <code>type</code> || <code>"content"</code> || <code>"content"</code> ||  
| loadMetadata || <code>type</code> || <code>"content"</code> || <code>"content"</code> || ||
|-
|-
|  || <code>assetid</code> || <code>"unique_id_500291"</code> || (unique per asset) ||  
|  || <code>assetid</code> || <code>"unique_id_500291"</code> || (unique per asset, no [[Special Characters]]) || ai ||  
|-
|-
|  || <code>length</code> || <code>"600"</code> || length in seconds (int or float) ||  
|  || <code>length</code> || <code>"600"</code> || length in seconds (int or float) || sd ||  
|-
|-
|  || <code>title</code> || <code>"Episode Title"</code> || (any non-empty value) ||  
|  || <code>title</code> || <code>"Episode Title"</code> || (any non-empty value) || tl ||  
|-
|-
|  || <code>program</code> || <code>"Show Name"</code> || (any non-empty value) ||  
|  || <code>program</code> || <code>"Show Name"</code> || (any non-empty value) || cg ||  
|-
|-
|  || <code>segB</code> || <code>"Primetime"</code> || (any value), used for optional breakdown ||  
|  || <code>segB</code> || <code>"Primetime"</code> || (any value), used for optional breakdown || c33 ||  
|-
|-
|  || <code>segC</code> || <code>"Comedy"</code> || (any value), used for optional breakdown ||  
|  || <code>segC</code> || <code>"Comedy"</code> || (any value), used for optional breakdown || c34 ||  
|-
|-
|  || <code>crossId1</code> || <code>"EP018S9S290015"</code> || Gracenote ID ||  
|  || <code>crossId1</code> || <code>"EP018S9S290015"</code> || Gracenote ID || c36 ||  
|-
|-
|  || <code>crossId2</code> || <code>"ABC"</code> || Network Name ||  
|  || <code>crossId2</code> || <code>"ABC"</code> || Network Name || c37 ||  
|-
|-
|  || <code>isfullepisode</code> || <code>"y"</code> || (<code>"y"</code> or <code>"n"</code>) (<code>"Y"</code> or <code>"N"</code>) ||  
|  || <code>isfullepisode</code> || <code>"y"</code> || (<code>"y"</code> or <code>"n"</code>) (<code>"Y"</code> or <code>"N"</code>) || c53 ||  
|-
|-
|  || <code>airdate</code> || <code>"20160206 23:00:00</code> || <code>"YYYYMMDD[space]HH:MM:SS"</code> -- note: HH=24 hour time ||  
|  || <code>airdate</code> || <code>"20160206 23:00:00"</code> || <code>"YYYYMMDD[space]HH:MM:SS"</code> -- note: HH=24 hour time || c54 ||  
|-
|-
|  || <code>adloadtype</code> || <code>"1"</code> || <code>"1"</code> for linear ads, <code>"2"</code> for DAI ||  
|  || <code>adloadtype</code> || <code>"1"</code> || <code>"1"</code> for linear ads, <code>"2"</code> for DAI || c57 ||  
|-
|-
|  || <code>hasAds</code> || <code>"1"</code> || <code>"0"</code> for no ads, <code>"1"</code> for has ads ||  
|  || <code>hasAds</code> || <code>"1"</code> || <code>"0"</code> for no ads, <code>"1"</code> for has ads || ||
|}
|}


=== loadMetadata() - ad ===
'''Sample View Ping'''
 
<code> <nowiki> https://secure-dcr.imrworldwide.com/cgi-bin/gn?prd=dcr&ci=us-123456&ch=us-123456_c01_P&asn=defChnAsset&fp_id=&fp_cr_tm=&fp_acc_tm=&fp_emm_tm=&ve_id=&devmodel=iPhone9%2C3&manuf=Apple&sysname=iOS&sysversion=13.6&sessionId=jpy5r0rzacm7vnglw3tciem00uj0r1616716185&tl=EpisodeTitle&prv=1&c6=vc,c01&ca=us-123456_c01_5b8fec026b66d17207730f67&cg=ProgramName&c13=asid,PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&
c32=segA,NA&c33=segB,SampleCustomReport1&c34=segC,SampleCustomReport2&c15=apn,SampleApp&plugv=&playerv=&sup=1&segment2=803&segment1=usa&forward=0&ad=1&cr=4_00_99_V1_00000&c9=devid,12b9377cbe7e5c94e8a70d9d23929523d14afa954793130f8a3959c7b849aca8&enc=true&c1=nuid,60c5df048574f38e6260fbfba08421cef92c2d6669b71ef4ca619127f3cafa70
&at=view&rt=video&c16=sdkv,ai.8.0.0&c27=cln,0&crs=&lat=&lon=&c29=plid,PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&c30=bldv,ai.8.0.0.gssaon&st=dcr&c7=osgrp,IOS&c8=devgrp,PHN&c10=plt,MBL&c40=adbid,&c14=osver,iOS11_2_1&c26=dmap,1&dd=&hrd=&wkd=&c35=adrsid,&c36=cref1,
&c37=cref2,&c11=agg,1&c12=apv,2.13.0.201&c51=adl,0&c52=noad,0&sd=2652&devtypid=iPhone8,2&pc=NA&c53=fef,yes&c54=oad,2018-09-05T14%3A00%3A00%2B00%3A00&c55=cref3,&c57=adldf,2&ai=VideoAssetID&c3=st,c&c64=starttm,1537206364&adid=5b8fec026b66d17207730f67&c58=isLive,false&c59=sesid,1537206364&c61=createtm,1537206364
&c63=pipMode,&c62=sendTime,1537206435&c68=bndlid,com.discovery.mobile.velgo&nodeTM=&logTM=&c73=phtype,Mobile+Phone&c74=dvcnm,Apple+iPhone&c76=adbsnid,&df=-1&c77=adsuprt,1&uoo=true&evdata=&c71=ottflg,0&c72=otttyp,&c44=progen,
&davty=0&si=&c66=mediaurl,https%253A%252F%252Fwww.samplesivalue.com%2FmediaURL%2Fexample%2Ffor%2Ftesting%2Fyour%2Fnielsen%2Fintegration%2Ffor%2FApp%2FSDK&vtoff=71&rnd=1537206435082</nowiki> </code>
 
===== loadMetadata() for DCR Ads =====
* Called at beginning of ad, or when resuming ad from interruption
* Called at beginning of ad, or when resuming ad from interruption
{| class="wikitable"
{| class="wikitable"
Line 116: Line 173:
|}
|}


=== setPlayheadPosition() - Preroll ad ===
===== setPlayheadPosition() for DCR =====
* Track current position of playhead
* Track current position of playhead
* Starts at 0 at the beginning of ad
* Updated at least once per second
* Updated at least once per second
* Separate playhead position for ads and content, should accurately reflect current position in either ads or content
* Separate playhead position for ads and content, should accurately reflect current position in either ads or content
Line 126: Line 182:
! Test Case !! Test Condition !! Pass/Fail
! Test Case !! Test Condition !! Pass/Fail
|-
|-
| <code>setPlayehadPosition</code> || Called every second ||
| <code>setPlayeheadPosition()</code> || Called every second ||  
|-
| <code>stop()</code> || Called at the end of Ad ||  
|}
|}


=== loadMetadata() - Content ===
===== stop() =====
* Test is to validate Content metadata is the same as original metadata passed during initial loadMetadata call.
* Indicates one of the following:
* Playback of content or ad was interrupted
* Reached end of ad (no parameters or metadata)
 
{| class="wikitable"
{| class="wikitable"
|-
|-
! Test !! Param !! Example Value !! Accepted Values !! Pass/Fail
! Test Case !! Test Condition !! Pass/Fail
|-
|-
| loadMetadata || <code>type</code> || <code>"content"</code> || <code>"content"</code> ||
| <code>stop()</code> || Called at the end of Ad or interrupt scenario||
|}
 
===== end() =====
* Reached the end of content (no parameters or metadata)
 
{| class="wikitable"
|-
|-
|  || <code>assetid</code> || <code>"unique_id_500291"</code> || (unique per asset) ||
! Test Case !! Test Condition !! Pass/Fail
|-
|-
|  || <code>length</code> || <code>"600"</code> || length in seconds (int or float) ||  
| <code>end()</code> || Reached the end of content (no parameters or metadata)||  
|}
 
==== SDK DTVR Events ====
 
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 for DTVR
 
<!--[[File:appsdkTimeline-DTVR-V2.png|icon]]-->
{| class="wikitable"
|-
|-
|  || <code>title</code> || <code>"Episode Title"</code> || (any non-empty value) ||
! Event !! Parameter !! Description
|-
|-
| || <code>program</code> || <code>"Show Name"</code> || (any non-empty value) ||  
|'play'||||Call when starting or resuming a streaming session.
'''Note:'''no longer required for SDK version 7.2 or higher.
|-
|-
| || <code>segB</code> || <code>"Primetime"</code> || (any value), used for optional breakdown ||  
| 'loadMetadata' || content/ad metadata object || Needs to be called at the beginning of each asset to pass type and adModel.
|-
|-
| || <code>segC</code> || <code>"Comedy"</code> || (any value), used for optional breakdown ||  
| 'sendID3' || Used to send the ID3 tag payload retrieved from the stream || Needs to be called at the beginning of playback
|-
|-
| || <code>crossId1</code> || <code>"EP018S9S290015"</code> || Gracenote ID ||
| 'stop' || playhead position || Call when content or ads complete playing and pass playhead position
'''Note:'''no longer required for SDK version 7.2 or higher.
|}
 
===== play() =====
* The '''play()''' call is required only once per viewing session (until app or SDK instance is killed)
* Called just before playback commences for first piece of content
{| class="wikitable"
|-
|-
|  || <code>crossId2</code> || <code>"ABC"</code> || Network Name ||
! Test Case !! Param !! Expected Result !! Pass/Fail
|-
|-
| || <code>isfullepisode</code> || <code>"y"</code> || (<code>"y"</code> or <code>"n"</code>) (<code>"Y"</code> or <code>"N"</code>) ||
| Play || <code>channelname</code> || Name of Channel ||  
|}
 
===== loadMetadata() for DTVR =====
{| class="wikitable"
|-
|-
|  || <code>airdate</code> || <code>"20160206 23:00:00</code> || <code>"YYYYMMDD[space]HH:MM:SS"</code> -- note: HH=24 hour time ||
! Test !! Param !! Example Value !! Accepted Values !! Pass/Fail
|-
|-
| || <code>adloadtype</code> || <code>"1"</code> || <code>"1"</code> for linear ads, <code>"2"</code> for DAI ||  
| loadMetadata || <code>type</code> || <code>"content"</code> || <code>"content"</code> ||  
|-
|-
|  || <code>hasAds</code> || <code>"1"</code> || <code>"0"</code> for no ads, <code>"1"</code> for has ads ||  
|  || <code>adModel</code> || <code>"1"</code> || <code>"1"</code> for linear ads ||  
|}
|}


=== setPlayheadPosition() - Content ===
===== sendID3() for DTVR Only =====
* Track current position of playhead
* sendID3 API is a receiver for timed metadata events (ID3 tags)
* Starts at 0 at the beginning of content
* Updated at least once per second
* Separate playhead position for ads and content, should accurately reflect current position in either ads or content
* Final playhead position for content must equal the length specified in loadMetadata(), followed by end() call
{| class="wikitable"
{| class="wikitable"
|-
|-
! Test Case !! Test Condition !! Pass/Fail
! Test Case !! Test Condition !! Pass/Fail
|-
|-
| <code>setPlayehadPosition</code> || Called every second ||
| <code>sendID3()</code> || Called approx. 10 second ||  
|-
| <code>stop()</code> || Called at the end of Content ||  
|}
|}
'''Sample ID3 Tag:'''
<code><nowiki>www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGheFi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9
xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00</nowiki></code>


=== stop() ===
===== stop() =====
* Indicates one of the following:
* Indicates one of the following:
* Playback of content or ad was interrupted
* Playback of content or ad was interrupted
* Reached end of ad (no parameters or metadata)
* Reached end of ad (no parameters or metadata)


=== end() ===
{| class="wikitable"
* Reached the end of content (no parameters or metadata)
|-
! Test Case !! Test Condition !! Pass/Fail
|-
| <code>stop()</code> || Called at the end of Ad or interrupt scenario||
|}
 
==== SDK DCR Static Events ====


== Interruptions ==
===== loadMetadata() for App or staticstart() for Browser =====
* All interruptions to playback of content or ads should trigger a call to stop(). Once the interruption is over, loadMetadata() with the same metadata should be called, followed by playheadPosition resuming from where it left off.
Called with correct metadata


* Interruptions include:
** user-induced pause
** screen turned off
** app sent to background
** headphones removed (note, if app simply switches audio output from headphones to speaker without pausing, there is no need to call stop())
** alarm/call interruption
** internet connection lost (n.b. cached playback plays as normal until it expires)
{| class="wikitable"
{| class="wikitable"
|-
|-
! Test Case !! Test Condition !! Pass/Fail
! Key !! Description !! Data Type !! Value !! Required? !! Pass/Fail
|-
| type || asset type || fixed || <code>'static'</code> || Yes ||
|-
|-
| user-induced pause || <code>stop()</code>, <code>loadMetadata()</code> & <code>playheadPosition</code> ||  
| assetid || Unique ID for each article || dynamic || custom <br>(no [[Special Characters]]) || Yes ||
|-
|-
| screen turned off || <code>stop()</code>, <code>loadMetadata()</code> & <code>playheadPosition</code> ||  
| 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||
|-
|-
| app sent to background || <code>stop()</code>, <code>loadMetadata()</code> & <code>playheadPosition</code> ||  
| segA || custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) || dynamic || custom || No ||
|-
|-
| headphones removed || <code>stop()</code>, <code>loadMetadata()</code> & <code>playheadPosition</code> ||  
| segB || custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) || dynamic || custom || No ||
|-
|-
| alarm/call interruption || <code>stop()</code>, <code>loadMetadata()</code> & <code>playheadPosition</code> ||  
| segC || custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) || dynamic || custom || No ||
|}
 
The values passed through the Nielsen keys will determine the breakouts that are seen in reporting. The custom segments (A, B & C) will roll into the sub-brand. To not use custom segments A, B and C, do not pass any value in these keys.
 
'''Aggregation Limits'''
There are limits on the number of unique values that can be aggregated on in reporting. The specific limitations by key are:
{| class="wikitable"
|-
|-
| internet connection lost || <code>stop()</code>, <code>loadMetadata()</code> & <code>playheadPosition</code> ||
! Key !! Aggregation Limit
|-
|-
| content paused || <code>playheadPosition</code> is not passed ||
| section || maximum of 25 unique values (section <= 25)
|-
|-
| resume content || <code>loadMetadata()</code> is called for content ||
| segA || Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25)
|-
|-
| || <code>loadMetadataM</code> is the same as original ||
| segB || Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25)
|-
|-
| || <code>playheadPosition</code> continues from resumed position ||
| segC || Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25)
|}
|}


===== staticEnd() =====
Ends DCR static duration measurement of current page/section/asset. Call staticEnd when a new DCR static view event is desired for subsequent loadMetadata call with same section name. The default behavior of AppSDK is to ignore a static loadMetadata call unless the section parameter is different. By calling staticEnd, a new view event can be initiated even in cases where section parameter is the same as previous metaData. This can happen with single-page or single-panel apps.


'''Expected SDK behavior for all interruptions:'''
{| class="wikitable"
# interruption triggers stop() call
|-
# when content resumes, loadMetadata() is called with the same metadata that was playing previously (ad or content)
! Test Case !! Test Condition !! Pass/Fail
# playheadPosition() resumes from the same position before the interruption
|-
| <code>staticEnd()</code> || Called when leaving page or using the same section parameter for a different page||
|}


'''Example session:'''
=== Interrupt Scenarios ===
* 5 minutes of content played, call interruption, content resumes until end of 15 min video
There are various interrupt scenarios. Test if Applicable


== Scrubbing ==
{| class="wikitable"
{| class="wikitable"
|-
|-
! Test Case !! Test Condition !! Pass/Fail
! Test Case !! Description !! Pass/Fail  
|-
| Pause / Play ||
* Call stop as soon as video is paused and withhold sending the playhead position.
* Once the video has resumed, call loadMetadata and sendID3 / playheadPosition in that order
||
|-
| Network loss (Wi-Fi / Airplane / Cellular) ||
* Call stop as soon as network is lost and withhold sending the playhead position.
* Once the Wi-Fi is ON / Airplane is OFF / Cellular network is ON and the video has resumed, call loadMetadata and sendID3 / playheadPosition in that order.
||
|-
|-
| Scrub Backward || new playhead position is accurate ||  
| Call Interrupt ( SIM or Third party Skype / Hangout call)||  
* Call stop as soon as a SIM or Skype / Hangout call is observed and withhold sending the playhead position.
* Once the SIM or Skype / Hangout call ends and the video has resumed, call loadMetadata and sendID3 / playheadPosition
||
|-
|-
| || new playhead continues from new position ||  
| Alarm Interrupt ||  
* Call stop as soon as a device or an in-app alarm is observed and withhold sending the playhead position.
* Once the device or in-app alarm ends / is acknowledged and the video has resumed, call loadMetadata and sendID3 / playheadPosition in that order.
||
|-
|-
| Scrub Forward || new playhead position is accurate ||  
| Content Buffering ||  
* Should withhold sending the playhead position as soon as player starts content buffering
* Once the buffering ends and the audio has resumed, call sendID3 / playheadPosition.
||
|-
|-
| || new playhead continues from new position ||  
| Lock / Unlock device ||  
* Call stop as soon as the device is locked and withhold sending the playhead position.
* Once the device is unlocked and the video has resumed, call loadMetadata and sendID3 / playheadPosition in that order.
||
|-
|-
| Scrub to end || final playhead position is passed ||  
| App going Background / Foreground (when PIP mode is not supported / enabled) ||  
* Call stop as soon as the app goes to background and withhold sending the playhead position.
* Once the app resumes to foreground and the video has resumed, call loadMetadata and sendID3 / playheadPosition in that order.
||
|-
|-
| || end event called at completion of content playback ||  
| Channel / Station change from current channel / station to other ||  
* Call stop for the current channel / station as soon as it is changed and withhold sending its playhead position.
* As soon as new channel / station starts, call loadMetadata and sendID3 / playheadPosition for the channel / station in that order.
||
|-
|-
| Scrub past midroll || Playhead for content stops ||  
| Unplugging of headphone ||  
* Call stop as soon as the video stops playback because of unplugging of headphone and withhold sending its playhead position.
* As soon as video resumes, call loadMetadata and sendID3 / playheadPosition
||
|}
|}


== Midroll & Postroll Ads ==
=== Scrubbing ===
{| class="wikitable"
{| class="wikitable"
|-
|-
! Test Case !! Test Condition !! Pass/Fail
! Test Case !! Test Condition !! Pass/Fail
|-
|-
| <code>loadMetadata()</code> || Called for each Ad ||  
| rowspan="2" | Scrub Backward || new playhead position is accurate ||  
|-
|-
|| Required Metadata is accurate ||  
new playhead continues from new position ||  
|-
|-
| <code>playheadPosition</code> || Passed every second ||  
| rowspan="2" | Scrub Forward || new playhead position is accurate ||  
|-
|-
| <code>stop()</code> || called for each ad ||  
| new playhead continues from new position ||  
|-
|-
| <code>loadMetadata()</code>, <code>playheadPosition</code>, <code>stop()</code> || correct sequence for each ad ||  
| rowspan="2" | Scrub to end || final playhead position is passed ||
|-
|  end event called at completion of content playback ||
|-
| Scrub past midroll || Playhead for content stops ||  
|}
|}


== Opt-Out ==
=== Opt-Out ===
Users must have access to "About Nielsen Measurement" page. User can click this page from app settings screen.
Users must have access to "About Nielsen Measurement" page. User can click this page from app settings screen.
* URL to this web page should be called from SDK by invoking optOutURL and opened in 'WebView' / External browser.
* URL to this web page should be called from SDK by invoking optOutURL and opened in 'WebView' / External browser.
Line 276: Line 402:
! Test Case !! Test Condition !! Pass/Fail
! Test Case !! Test Condition !! Pass/Fail
|-
|-
| <code>optOutView</code> || User can Opt-Out ||  
| <code>optOutView</code> || User can Opt-Out ||
|}
|}

Latest revision as of 19:52, 27 April 2023

Engineering Portal breadcrumbArrow.png Digital breadcrumbArrow.png DCR & DTVR breadcrumbArrow.png Digital Pre-Certification Checklist App SDK

Pre-Certification Checklist

Before starting the certification process, please verify the following steps have been completed.

  • Your Client Service representative should have already discussed a reporting hierarchy with you -- along with a Parent, Brand, and Sub-brand/Channel
  • Your Integration Engineer should have:
    • provided you with an AppID
    • informed you of our Opt-Out requirement for a WebView inside your apps
  • Retrieving AppSDK logs
    • 'nol_devDebug' : 'DEBUG' should be present in initialization call (see below)
    • Android: use adb logcat (note: requires Android Studio)
    • iOS: idevicesyslog (note: requires XCode)

Test Cases

The following lists the test cases along with expected results:


Note: Due to the variable and unique nature of each application, there may be additional testing required by Nielsen that is not listed here. These tests are completed to ensure the quality of data collected. Please speak with your account manager if you have any questions.

Initialization

The first step in the Certification process is to ensure that the Nielsen SDK is initializing at app startup, and that the global metadata values are present.

Keys Value
appid XXXXX-XXXXXX-XXXXX-XXXXX
appname example app name
appversion 2.0
nol_devDebug debug

iOS Example:

NSDictionary* appInformation = @
{ // AppID is Nielsen-supplied
	 @"appid": @"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
 	 @"appname": @"Sample App Name",
 	 @"appversion": @"2.0",
 	 @"nol_devDebug": @"DEBUG" // required for testing only
}

Android Example:

JSONObject appSdkConfig = new JSONObject()
          .put("appid", "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")
          .put("appname", "Sample App Name")
          .put("appversion","2.0")
          .put("nol_devDebug", "DEBUG"); // required for testing only
// Pass appSdkConfig to the AppSdk constructor
mAppSdk = new AppSdk(appContext, appSdkConfig, appSdkListener);


Config Ping

Confirm that SDK initialization is occurring at app start-up by presence of configuration ping.

Sample Ping: https://cdn-gl.imrworldwide.com/conf/PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX.json?devtypid=iPhone8,2&devid=12b9377cbe7e5c94e8a70d9d23929523d14afa954793130f8a3959c7b849aca8 &devname=My%20iPhone&osver=iOS13.6&sysname=iOS&bid=com.nielsen.com.test.config

App ID Description
PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX Should be your App ID for the integration

SDK Event Sequence Check

SDK DCR Video Events

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 for DCR.

Type Sample Code Description
Start of stream mAppSdk.play(); // stream starts
mAppSdk.loadMetadata(contentMetaDataObject); // contentMetadataObject contains the JSON metadata for the content being played
Preroll mAppSdk.loadMetadata(prerollMetadataObject); // prerollMetadataObject contains the JSON metadata for the preroll ad
mAppSdk.playheadPosition(playheadPosition); // position is position of the playhead while the preroll ad is being played
mAppSdk.stop(); // Call stop after preroll occurs
Content mAppSdk.loadMetadata(contentMetaDataObject); // contentMetadataObject contains the JSON metadata for the content being played
mAppSdk.playheadPosition(playheadPosition); // position is position of the playhead while the content is being played
Midroll mAppSdk.loadMetadata(midrollMetaDataObject); // midrollMetadataObject contains the JSON metadata for the midroll ad
mAppSdk.playheadPosition(playheadPosition); // position is position of the playhead while the midroll ad is being played
mAppSdk.stop(); // Call stop after midroll occurs
Content Resumes mAppSdk.loadMetadata(contentMetaDataObject); // contentMetadataObject contains the JSON metadata for the content being played
mAppSdk.playheadPosition(playheadPosition); // position is position of the playhead while the content is being played
End of Stream mAppSdk.end(); // Call end() at the end of content
Postroll mAppSdk.loadMetadata(postrollMetaDataObject); // postrollMetadataObject contains the JSON metadata for the postroll ad
mAppSdk.playheadPosition(playheadPosition); // position is position of the playhead while the postroll ad is being played
mAppSdk.stop(); // Call stop after postroll occurs

Note: Each Ad playhead should 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.

play()
  • Call at start of each new stream before playback commences
Test Case Param Expected Result Pass/Fail
Play channelname Name of Channel
loadMetadata() for DCR Content
  • Called at beginning of content, or when resuming content from interruption or ad
Test Param Example Value Accepted Values Ping Parameter Pass/Fail
loadMetadata type "content" "content"
assetid "unique_id_500291" (unique per asset, no Special Characters) ai
length "600" length in seconds (int or float) sd
title "Episode Title" (any non-empty value) tl
program "Show Name" (any non-empty value) cg
segB "Primetime" (any value), used for optional breakdown c33
segC "Comedy" (any value), used for optional breakdown c34
crossId1 "EP018S9S290015" Gracenote ID c36
crossId2 "ABC" Network Name c37
isfullepisode "y" ("y" or "n") ("Y" or "N") c53
airdate "20160206 23:00:00" "YYYYMMDD[space]HH:MM:SS" -- note: HH=24 hour time c54
adloadtype "1" "1" for linear ads, "2" for DAI c57
hasAds "1" "0" for no ads, "1" for has ads

Sample View Ping

https://secure-dcr.imrworldwide.com/cgi-bin/gn?prd=dcr&ci=us-123456&ch=us-123456_c01_P&asn=defChnAsset&fp_id=&fp_cr_tm=&fp_acc_tm=&fp_emm_tm=&ve_id=&devmodel=iPhone9%2C3&manuf=Apple&sysname=iOS&sysversion=13.6&sessionId=jpy5r0rzacm7vnglw3tciem00uj0r1616716185&tl=EpisodeTitle&prv=1&c6=vc,c01&ca=us-123456_c01_5b8fec026b66d17207730f67&cg=ProgramName&c13=asid,PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX& c32=segA,NA&c33=segB,SampleCustomReport1&c34=segC,SampleCustomReport2&c15=apn,SampleApp&plugv=&playerv=&sup=1&segment2=803&segment1=usa&forward=0&ad=1&cr=4_00_99_V1_00000&c9=devid,12b9377cbe7e5c94e8a70d9d23929523d14afa954793130f8a3959c7b849aca8&enc=true&c1=nuid,60c5df048574f38e6260fbfba08421cef92c2d6669b71ef4ca619127f3cafa70 &at=view&rt=video&c16=sdkv,ai.8.0.0&c27=cln,0&crs=&lat=&lon=&c29=plid,PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&c30=bldv,ai.8.0.0.gssaon&st=dcr&c7=osgrp,IOS&c8=devgrp,PHN&c10=plt,MBL&c40=adbid,&c14=osver,iOS11_2_1&c26=dmap,1&dd=&hrd=&wkd=&c35=adrsid,&c36=cref1, &c37=cref2,&c11=agg,1&c12=apv,2.13.0.201&c51=adl,0&c52=noad,0&sd=2652&devtypid=iPhone8,2&pc=NA&c53=fef,yes&c54=oad,2018-09-05T14%3A00%3A00%2B00%3A00&c55=cref3,&c57=adldf,2&ai=VideoAssetID&c3=st,c&c64=starttm,1537206364&adid=5b8fec026b66d17207730f67&c58=isLive,false&c59=sesid,1537206364&c61=createtm,1537206364 &c63=pipMode,&c62=sendTime,1537206435&c68=bndlid,com.discovery.mobile.velgo&nodeTM=&logTM=&c73=phtype,Mobile+Phone&c74=dvcnm,Apple+iPhone&c76=adbsnid,&df=-1&c77=adsuprt,1&uoo=true&evdata=&c71=ottflg,0&c72=otttyp,&c44=progen, &davty=0&si=&c66=mediaurl,https%253A%252F%252Fwww.samplesivalue.com%2FmediaURL%2Fexample%2Ffor%2Ftesting%2Fyour%2Fnielsen%2Fintegration%2Ffor%2FApp%2FSDK&vtoff=71&rnd=1537206435082

loadMetadata() for DCR Ads
  • Called at beginning of ad, or when resuming ad from interruption
Test Param Example Value Accepted Values Pass/Fail
loadMetadata assetid "ad_2201343201" (any non-empty value)
type "midroll" "preroll", "midroll", "postroll" Example
setPlayheadPosition() for DCR
  • Track current position of playhead
  • Updated at least once per second
  • Separate playhead position for ads and content, should accurately reflect current position in either ads or content
  • Final playhead position for content must equal the length specified in loadMetadata(), followed by end() call
Test Case Test Condition Pass/Fail
setPlayeheadPosition() Called every second
stop()
  • Indicates one of the following:
  • Playback of content or ad was interrupted
  • Reached end of ad (no parameters or metadata)
Test Case Test Condition Pass/Fail
stop() Called at the end of Ad or interrupt scenario
end()
  • Reached the end of content (no parameters or metadata)
Test Case Test Condition Pass/Fail
end() Reached the end of content (no parameters or metadata)

SDK DTVR Events

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 for DTVR

Event Parameter Description
'play' Call when starting or resuming a streaming session.

Note:no longer required for SDK version 7.2 or higher.

'loadMetadata' content/ad metadata object Needs to be called at the beginning of each asset to pass type and adModel.
'sendID3' Used to send the ID3 tag payload retrieved from the stream Needs to be called at the beginning of playback
'stop' playhead position Call when content or ads complete playing and pass playhead position

Note:no longer required for SDK version 7.2 or higher.

play()
  • The play() call is required only once per viewing session (until app or SDK instance is killed)
  • Called just before playback commences for first piece of content
Test Case Param Expected Result Pass/Fail
Play channelname Name of Channel
loadMetadata() for DTVR
Test Param Example Value Accepted Values Pass/Fail
loadMetadata type "content" "content"
adModel "1" "1" for linear ads
sendID3() for DTVR Only
  • sendID3 API is a receiver for timed metadata events (ID3 tags)
Test Case Test Condition Pass/Fail
sendID3() Called approx. 10 second

Sample ID3 Tag: www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGheFi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9 xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00

stop()
  • Indicates one of the following:
  • Playback of content or ad was interrupted
  • Reached end of ad (no parameters or metadata)
Test Case Test Condition Pass/Fail
stop() Called at the end of Ad or interrupt scenario

SDK DCR Static Events

loadMetadata() for App or staticstart() for Browser

Called with correct metadata

Key Description Data Type Value Required? Pass/Fail
type asset type fixed 'static' Yes
assetid Unique ID for each article dynamic custom
(no Special Characters)
Yes
section section of each site (e.g. section value should be first level in page URL: website.com/section). Limit to 25 unique values dynamic custom Yes
segA custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) dynamic custom No
segB custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) dynamic custom No
segC custom segment for reporting: Limit to 25 unique values across custom segments (segA + segB + segC) dynamic custom No

The values passed through the Nielsen keys will determine the breakouts that are seen in reporting. The custom segments (A, B & C) will roll into the sub-brand. To not use custom segments A, B and C, do not pass any value in these keys.

Aggregation Limits There are limits on the number of unique values that can be aggregated on in reporting. The specific limitations by key are:

Key Aggregation Limit
section maximum of 25 unique values (section <= 25)
segA Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25)
segB Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25)
segC Maximum number of unique values allowed across segA, segB, and segC is 25 (segA + segB + segC<= 25)
staticEnd()

Ends DCR static duration measurement of current page/section/asset. Call staticEnd when a new DCR static view event is desired for subsequent loadMetadata call with same section name. The default behavior of AppSDK is to ignore a static loadMetadata call unless the section parameter is different. By calling staticEnd, a new view event can be initiated even in cases where section parameter is the same as previous metaData. This can happen with single-page or single-panel apps.

Test Case Test Condition Pass/Fail
staticEnd() Called when leaving page or using the same section parameter for a different page

Interrupt Scenarios

There are various interrupt scenarios. Test if Applicable

Test Case Description Pass/Fail
Pause / Play
  • Call stop as soon as video is paused and withhold sending the playhead position.
  • Once the video has resumed, call loadMetadata and sendID3 / playheadPosition in that order
Network loss (Wi-Fi / Airplane / Cellular)
  • Call stop as soon as network is lost and withhold sending the playhead position.
  • Once the Wi-Fi is ON / Airplane is OFF / Cellular network is ON and the video has resumed, call loadMetadata and sendID3 / playheadPosition in that order.
Call Interrupt ( SIM or Third party Skype / Hangout call)
  • Call stop as soon as a SIM or Skype / Hangout call is observed and withhold sending the playhead position.
  • Once the SIM or Skype / Hangout call ends and the video has resumed, call loadMetadata and sendID3 / playheadPosition
Alarm Interrupt
  • Call stop as soon as a device or an in-app alarm is observed and withhold sending the playhead position.
  • Once the device or in-app alarm ends / is acknowledged and the video has resumed, call loadMetadata and sendID3 / playheadPosition in that order.
Content Buffering
  • Should withhold sending the playhead position as soon as player starts content buffering
  • Once the buffering ends and the audio has resumed, call sendID3 / playheadPosition.
Lock / Unlock device
  • Call stop as soon as the device is locked and withhold sending the playhead position.
  • Once the device is unlocked and the video has resumed, call loadMetadata and sendID3 / playheadPosition in that order.
App going Background / Foreground (when PIP mode is not supported / enabled)
  • Call stop as soon as the app goes to background and withhold sending the playhead position.
  • Once the app resumes to foreground and the video has resumed, call loadMetadata and sendID3 / playheadPosition in that order.
Channel / Station change from current channel / station to other
  • Call stop for the current channel / station as soon as it is changed and withhold sending its playhead position.
  • As soon as new channel / station starts, call loadMetadata and sendID3 / playheadPosition for the channel / station in that order.
Unplugging of headphone
  • Call stop as soon as the video stops playback because of unplugging of headphone and withhold sending its playhead position.
  • As soon as video resumes, call loadMetadata and sendID3 / playheadPosition

Scrubbing

Test Case Test Condition Pass/Fail
Scrub Backward new playhead position is accurate
new playhead continues from new position
Scrub Forward new playhead position is accurate
new playhead continues from new position
Scrub to end final playhead position is passed
end event called at completion of content playback
Scrub past midroll Playhead for content stops

Opt-Out

Users must have access to "About Nielsen Measurement" page. User can click this page from app settings screen.

  • URL to this web page should be called from SDK by invoking optOutURL and opened in 'WebView' / External browser.
  • If the App SDK returns NULL as Opt-Out URL, handle the exception gracefully and retry later.
  • To retrieve the current Opt-Out status of a device, use the optOutStatus method.
Test Case Test Condition Pass/Fail
optOutView User can Opt-Out