Digital Pre-Certification Checklist App SDK
From Engineering Client Portal
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 |