Digital Pre-Certification Checklist App SDK: Difference between revisions
From Engineering Client Portal
No edit summary |
NickParrucci (talk | contribs) No edit summary |
||
(11 intermediate revisions by 4 users not shown) | |||
Line 2: | Line 2: | ||
[[Category:Digital]] | [[Category:Digital]] | ||
== Pre- | == 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 | * Your Integration Engineer should have: | ||
** provided you with an AppID | ** provided you with an AppID | ||
** 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) | ||
** 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(" | .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> | ||
== | |||
The | === 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" | ||
|- | |- | ||
! | ! 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 | |||
|- | |- | ||
| | | End of Stream || <code>mAppSdk.end();</code> || // Call end() at the end of content | ||
|- | |- | ||
| | | rowspan="3" | Postroll || <code>mAppSdk.loadMetadata(postrollMetaDataObject);</code> || // postrollMetadataObject contains the JSON metadata for the postroll ad | ||
|- | |- | ||
| <code>mAppSdk.playheadPosition(playheadPosition);</code> || // position is position of the playhead while the postroll ad is being played | |||
|- | |- | ||
| <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> | ||
* | |||
===== play() ===== | |||
* Call at start of each new stream before playback commences | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 72: | Line 120: | ||
|} | |} | ||
=== loadMetadata() | ===== 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() | '''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() | ===== setPlayheadPosition() for DCR ===== | ||
* Track current position of playhead | * Track current position of playhead | ||
* 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> | | <code>setPlayeheadPosition()</code> || Called every second || | ||
|} | |} | ||
=== | ===== stop() ===== | ||
* | * 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 !! | ! Test Case !! Test Condition !! Pass/Fail | ||
|- | |- | ||
| <code>stop()</code> || Called at the end of Ad or interrupt scenario|| | |||
|} | |||
===== end() ===== | |||
* Reached the end of content (no parameters or metadata) | |||
{| class="wikitable" | |||
|- | |- | ||
! Test Case !! Test Condition !! Pass/Fail | |||
|- | |- | ||
| <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" | |||
|- | |- | ||
! 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 | |||
{| class="wikitable" | |||
|- | |- | ||
! Test Case !! Param !! Expected Result !! Pass/Fail | |||
|- | |- | ||
| | | Play || <code>channelname</code> || Name of Channel || | ||
|} | |||
===== loadMetadata() for DTVR ===== | |||
{| class="wikitable" | |||
|- | |- | ||
! Test !! Param !! Example Value !! Accepted Values !! Pass/Fail | |||
|- | |- | ||
| | | loadMetadata || <code>type</code> || <code>"content"</code> || <code>"content"</code> || | ||
|- | |- | ||
| || <code> | | || <code>adModel</code> || <code>"1"</code> || <code>"1"</code> for linear ads || | ||
|} | |} | ||
=== | ===== sendID3() for DTVR Only ===== | ||
* | * sendID3 API is a receiver for timed metadata events (ID3 tags) | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Test Case !! Test Condition !! Pass/Fail | ! Test Case !! Test Condition !! Pass/Fail | ||
|- | |- | ||
| <code> | | <code>sendID3()</code> || Called approx. 10 second || | ||
|} | |} | ||
'''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) | ||
= | {| class="wikitable" | ||
|- | |||
! Test Case !! Test Condition !! Pass/Fail | |||
|- | |||
| <code>stop()</code> || Called at the end of Ad or interrupt scenario|| | |||
|} | |||
==== SDK DCR Static Events ==== | |||
== | ===== loadMetadata() for App or staticstart() for Browser ===== | ||
Called with correct metadata | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! | ! Key !! Description !! Data Type !! Value !! Required? !! Pass/Fail | ||
|- | |||
| type || asset type || fixed || <code>'static'</code> || Yes || | |||
|- | |- | ||
| | | assetid || Unique ID for each article || dynamic || custom <br>(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: | |||
{| class="wikitable" | |||
|- | |- | ||
! 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. | |||
{| class="wikitable" | |||
|- | |||
! Test Case !! Test Condition !! Pass/Fail | |||
|- | |||
| <code>staticEnd()</code> || Called when leaving page or using the same section parameter for a different page|| | |||
|} | |||
=== Interrupt Scenarios === | |||
There are various interrupt scenarios. Test if Applicable | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Test Case !! | ! 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 === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Test Case !! Test Condition !! Pass/Fail | ! Test Case !! Test Condition !! Pass/Fail | ||
|- | |- | ||
| | | rowspan="2" | Scrub Backward || new playhead position is accurate || | ||
|- | |- | ||
| | | new playhead continues from new position || | ||
|- | |- | ||
| | | rowspan="2" | Scrub Forward || new playhead position is accurate || | ||
|- | |- | ||
| | | new playhead continues from new position || | ||
|- | |- | ||
| | | 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 Digital DCR & DTVR 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 |
|
|
Network loss (Wi-Fi / Airplane / Cellular) |
|
|
Call Interrupt ( SIM or Third party Skype / Hangout call) |
|
|
Alarm Interrupt |
|
|
Content Buffering |
|
|
Lock / Unlock device |
|
|
App going Background / Foreground (when PIP mode is not supported / enabled) |
|
|
Channel / Station change from current channel / station to other |
|
|
Unplugging of headphone |
|
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 |