iOS Step By Step
From Engineering Client Portal
Provided below are step-by-step quick start guides for implementing Nielsen iOS SDK for DCR Static, DCR Video, and DTVR products. Click each section to get started.
→ iOS DCR Static
Show/hide DCR Static
iOS DCR Static Introduction
Show/hide Intro
The Digital Content Ratings (DCR) Static product provides content consumption measurement in client mobile apps and webpages. This measurement includes insight into the total time a user spent on a webpage, how they navigated through the page via links, and many other data points. This tutorial provides the steps to implement the DCR Static product in a sample iOS app. It includes:
- SDK Initialization Call
- DCR Static Metadata: information about the sections being tracked
By the end of this guide you will have the needed steps to integrate Nielsen's AppSDK in the background of your app.
iOS DCR Static Step 1 - Obtain AppID
Show/hide step 1
To begin using the iOS SDK (AppSDK) you will need to obtain an Application ID (AppId)
Item | Description | Source | |
---|---|---|---|
✅ | App ID (appid) | Unique ID assigned to the player/site and configured by product | Contact your Nielsen TAM |
The appid is a 37 character unique ID assigned to the player/site and configured by product and is required when creating a new instance of the AppSDK in the app.
Example: PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX
iOS DCR Static Step 2 - SDK Initialization
Show/hide step 2
How to obtain the NielsenAppApi.Framework
The Nielsen AppSDK can either be downloaded directly or can be integrated directly within an application through the use of CocoaPods. We recommend using the CocoaPods-based integration whenever possible to ensure you maintain the most recent changes and enhancements to the Nielsen libraries.
Configuring Xcode Development Environment
Starting with SDK version 6.0.0.0, the Nielsen App SDK is compatible with Apple iOS versions 8.0 and above. In addition, when using the dynamic framework, all the required frameworks are linked automatically as the are needed. More details can be found here: https://stackoverflow.com/questions/24902787/dont-we-need-to-link-framework-to-xcode-project-anymore
Note: All communications between the SDK and the Census (Collection Facility) use HTTPS.
Download Framework
The first step is to download and copy the NielsenAppApi.framework bundle to the app project directory. (Not required if using CocaPods)
Add Framework
In the General tab for app configuration add NielsenAppApi.framework in the list of Embedded Binaries. (Not required if using CocaPods)
Add Path
Add path to the NielsenAppApi.framework in the Framework Search Paths build setting. (Not required if using CocaPods)
Import Framework
Add NielsenAppApi.framework module in the source file of your app:
Using Swift
Add the following:
import NielsenAppApi
Using Objective-C
@import NielsenAppApi;
Sample SDK Initialization Code
Swift
Swift 4.0 Example:
NielsenInit.swift
import Foundation
import NielsenAppApi
class NielsenInit : NSObject {
class func createNielsenApi(delegate: NielsenAppApiDelegate) -> NielsenAppApi?{
let appInformation:[String: String] = [
"appid": "PDA7D5EE6-B1B8-4123-9277-2A788XXXXXXX",
"sfcode": "dcr",
"nol_devDebug": "DEBUG"
]
return NielsenAppApi(appInfo:appInformation, delegate:delegate)
}
}
Sample code using AVPlayer.
LandingVC.swift
import UIKit
import NielsenAppApi
class LandingVC: UIViewController, NielsenAppApiDelegate {
var nielsenMain : NielsenAppApi!
var sdkMethods : SDKMethods!
var data : [String : Any]!
class ViewController: UIViewController, NielsenAppApiDelegate, AVPlayerViewControllerDelegate {
// your code//
override func viewDidLoad() {
super.viewDidLoad()
//Getting the instance of NielsenApi
self.nielsenApi = NielsenInit.createNielsenApi(delegate: self)
}
}
override func viewDidAppear(_ animated: Bool) {
self.data = sdkMethods.loadStaticMaster() // This is just an example of populating the metadata
self.nielsenMain.loadMetadata(self.data)
}
Objective C
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:
If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.
#import "NielsenInit.h"
#import <NielsenAppApi/NielsenEventTracker.h>
@implementation NielsenInit
+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id<NielsenAppApiDelegate>)delegate
{
//Initialising the NielsenEventTracker class by passing app information which returns the instance of NielsenEventTracker.
NSDictionary *appInformation = @{ @"appid": @"PDA7D5EE6-B1B8-4123-9277-2A788XXXXXXX",
@"appversion": @"1.0",
@"sfcode": @"dcr",
@"nol_devDebug": @"DEBUG", };
return [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];
}
@end
The following would be the NielsenInit.h
file:
#import <Foundation/Foundation.h>
@class NielsenAppApi;
@protocol NielsenAppApiDelegate;
@interface NielsenInit : NSObject
+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id<NielsenAppApiDelegate>)delegate;
@end
Sample Code:
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//Getting the instance of Nielsen SDK
nielsenApi = [NielsenInit createNielsenAppApiWithDelegate:nil];
iOS DCR Static Step 3 - Create/Load DCR Static Metadata Object
Show/hide step 3
Configure Metadata
Map the Nielsen keys to variables so that the content metadata is dynamically updated.
The Nielsen reserved keys are:
Key | Description | Data Type | Value | Required? |
---|---|---|---|---|
type | asset type | fixed | 'static' |
Yes |
assetid | Unique ID for each article | dynamic | custom (no Special Characters) |
No |
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.
Configure API calls - loadMetadata
Use loadMetadata to pass 'content' Digital Measurement Metadata. The CMS data must be passed as a JSON object.
loadMetadata(JSONObject jsonMetadata);
Note: The loadMetadata call must have ("type": "static").
Call loadMetadata with JSON metadata as below.
new JSONObject()
.put("type", "static")
.put("section", "siteSection")
.put("assetid", "vid345-67483")
.put("segA", "segmentA")
.put("segB", "segmentB")
.put("segC","segmentC")
}
As soon as this loadMetadata call is made, AppSDK will record a view event and start tracking the section/page time spent (AppSDK 9.1 and above).
DCR Static Duration Measurement per Section/Page/Asset
If your Nielsen AppID is enabled for DCR Static duration measurement, a view event will be recorded and a timer will be started for each screen/page. Duration will be measured until a new page is loaded or the app is moved to the background. The event which triggers recognition of page view and timer start is the loadMetadata API call with a metadata object of type 'static'. Once a page is viewed and the timer has started, duration will be measured until a new page has loaded with associated loadMetadata call having a different section name from the previous page. If a new loadMetadata call is made with the same section name, it will be ignored - no new view will be recorded. If it is desired to have a new view event even though the metadata contains the same section name (example: single-page apps having several assedIDs but common section name), staticEnd API can be called between page views. For the purposes of this overview, staticend will not be used. See this page for more information.
Keep Going
Show/hide
Congratulations, you've successfully integrated the iOS SDK in your app!
You can add static loadMetadata calls for more sections/pages in your app to see what happens when transitioning between sections.
View your application's debug logs and search for the term (AppSDK) to see messages emitted by Nielsen AppSDK.
Next Steps
Show/hide
Now that you've integrated DCR Static for the AppSDK, what's next?
Going Live
In addition to the basic steps above, before going live developers need to handle app background/foreground events, make certain privacy disclosures, and allow users to opt out of Nielsen measurement. More details can be found here, along with a more comprehensive reference for implementing DCR Static measurement with AppSDK.
Once the DCR Tracking Code is added, Nielsen will validate the implementation. Following Nielsen testing, developers need to make a few updates to the initialization call to ensure that the app is being measured properly.
- App ID: Ensure that correct is used during initialization PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
- Debug Logging: Disable logging by changing initialization call to use @"nol_devDebug":@"INFO".
→ iOS DCR Video
Show/hide DCR Video
iOS DCR Video Introduction
Show/hide Intro
The Digital Content Ratings (DCR) Video product provides content consumption measurement in client mobile apps and webpages. This measurement includes insight into the total time a user spent watching the tracked content, video player events, and much more. This example provides the steps to implement the DCR Video product in a sample iOS app. It includes:
- SDK Initialization
- DCR Video Metadata: information about the content being tracked
- DCR Video Events/API calls
By the end of this guide you will have the needed steps to integrate Nielsen's AppSDK in the background of your app.
iOS DCR Video Step 1 - Obtain AppID
Show/hide step 1
To begin using the iOS AppSDK, you will need to obtain an Application ID (AppId)
Item | Description | Source | |
---|---|---|---|
✅ | App ID (appid) | Unique ID assigned to the player/site and configured by product | Contact your Nielsen Representative |
The appid is a 37 character unique ID assigned to the player/site and configured by product and is required when creating a new instance of the AppSDK in the app.
Example: PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX
iOS DCR Video Step 2 - SDK Initialization
Show/hide step 2
How to obtain the NielsenAppApi.Framework
The Nielsen AppSDK can either be downloaded directly or can be integrated directly within an application through the use of CocoaPods. We recommend using the CocoaPods-based integration whenever possible to ensure you maintain the most recent changes and enhancements to the Nielsen libraries.
Configuring Xcode Development Environment
Starting with SDK version 6.0.0.0, the Nielsen App SDK is compatible with Apple iOS versions 8.0 and above. In addition, when using the dynamic framework, all the required frameworks are linked automatically as the are needed. More details can be found here: https://stackoverflow.com/questions/24902787/dont-we-need-to-link-framework-to-xcode-project-anymore
Note: All communications between the SDK and the Census (Collection Facility) use HTTPS.
= Download Framework =
The first step is to download and copy the NielsenAppApi.framework bundle to the app project directory. (Not required if using CocaPods)
= Add Framework =
In the General tab for app configuration add NielsenAppApi.framework in the list of Embedded Binaries. (Not required if using CocaPods)
= Add Path =
Add path to the NielsenAppApi.framework in the Framework Search Paths build setting. (Not required if using CocaPods)
= Import Framework =
Add NielsenAppApi.framework module in the source file of your app:
= Using Swift =
Add the following:
import NielsenAppApi
= Using Objective-C =
@import NielsenAppApi;
= SDK Initialization =
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.
Parameter / Argument | Description | Source | Required? | Example |
---|---|---|---|---|
appid | Unique Nielsen ID for the application. The ID is a GUID data type. If you did not receive your App ID, let us know and we will provide you. | Nielsen-specified | Yes | PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX |
nol_devDebug | Enables Nielsen console logging. Only required for testing |
Nielsen-specified | Optional | DEBUG |
Debug flag for development environment
Player application developers / integrators can use Debug flag to check whether an App SDK API call made is successful. To activate the Debug flag,
Pass the argument @"nol_devDebug":@"DEBUG"
, in the JSON string .
Once the flag is active, it logs each API call made and the data passed. The log created by this flag is minimal.
Note: DO NOT activate the Debug flag in a production environment.
Swift Example
Sample SDK Initialization Code
NielsenInit.swift
class NielsenInit: NSObject {
class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -> NielsenAppApi?{
let appInformation:[String: String] = [
"appid": "PE392366B-F2C1-4BC4-AB62-A7DAFDCXXXX",
"nol_devDebug": "DEBUG"
]
return NielsenAppApi(appInfo:appInformation, delegate:delegate)}}
ViewController.swift
class ViewController: UIViewController, NielsenAppApiDelegate, AVPictureInPictureControllerDelegate, CLLocationManagerDelegate {
let avPlayerViewController = AVPlayerViewController()
var avPlayer:AVPlayer?
var nielsenAppApi: NielsenAppApi!
override func viewDidLoad() {
super.viewDidLoad()
self.nielsenAppApi = NielsenInit.createNielsenAppApi(delegate: self)
NSLog("Nielsen SDK initialized")
}}
Objective C
Sample SDK Initialization Code
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:
If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.
#import "NlsAppApiFactory.h"
#import <NielsenAppApi/NielsenAppApi.h>
@implementation NlsAppApiFactory
+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id<NielsenAppApiDelegate>)delegate;
{
NSDictionary *appInformation = @{
@"appid": "PE392366B-F2C1-4BC4-AB62-A7DAFDC51XXX",
@"nol_devDebug": @"DEBUG"
};
return [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];
}
@end
The following would be the NlsAppApiFactory.h
file:
#import <Foundation/Foundation.h>
@class NielsenAppApi;
@protocol NielsenAppApiDeligate;
@interface NlsAppApiFactory : NSObject
+ (NielsenAppAPI *) createNielsenAppApiWithDelegate:(id<NielsenAppApiDelegate>)delegate;
@end
}}
The following might be in the Viewcontroller.m
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//Setting background image
UIImage *backgroundImage = [UIImage imageNamed:@"new_ios_bg.png"];
UIImageView *backgroundImageView=[[UIImageView alloc]initWithFrame:self.view.frame];
backgroundImageView.image=backgroundImage;
[self.view insertSubview:backgroundImageView atIndex:0];
//Mark: In NielsenInit class we are initialising the Nielsen SDK.
//Getting the instance of Nielsen SDK
nielsenApi = [NielsenInit createNielsenAppApiWithDelegate:nil];
}
iOS DCR Video Step 3 - Create DCR Video Content Metadata Object
Show/hide step 3
Configure Metadata
The SDK methods handle only two types of objects: NSString, NSDictionary. The parameters passed must be either a JSON formatted string or a NSDictionary object. The JSON passed in the SDK must be well-formed.
- NSDictionary object
- If an object of unexpected type is passed to the method, the error message will be logged.
- If string has invalid JSON format, the error message will be logged.
- JSON value must be string value.
- This includes boolean and numeric values. For example, a value of true should be represented with "true", number value 123 should be "123".
- All the Nielsen Key names (e.g. appid, program) are case-sensitive. Use the correct variable name as specified in the documentation.
- JSON string can be prepared using either raw NSString or serialized NSDictionary.
Create channelName Metadata
channelName should remain constant throughout the completion of an episode or live stream.
Key | Description | Values | Required |
---|---|---|---|
channelName | Any string representing the channel/stream | custom | ✓ |
Create Content Metadata
Content metadata should remain constant throughout the entirety of an episode/clip including when ads play.
program and title metadata values should be passed to SDK as UTF-8 strings.
Keys | Description | Values | Required | Provider |
---|---|---|---|---|
type | Type of asset | For Video use: content For Static or text static |
Yes | Nielsen |
assetid | Unique ID assigned to asset Note: Refrain from using the following special characters (Special Characters). |
Examples: BBT345a234 CBSs5e234F2021 |
Yes | Client |
program | Complete program or movie title (no abbreviations or shorthand) Note: there is a 25 character limit. |
The Big Bang Theory TheBigBangTheory The Dark Knight TheDarkKnight |
Yes | Client |
title | Episode title with season and episode number (40 character limit) (Formats accepted: S01E03, S1E3, S1 E3). |
Examples: The Pants Alternative S03E18 The Pants Alternative S3E18 The Pants Alternative S3 E18 Can also accept: S3E18 Not Valid: 318 or 0318 |
Yes | Client |
crossId1 | Gracenote TMS ID (If available) should be passed for all telecasted content for clients using the Gracenote solution for proper matching purposes. Note: The TMS ID will be a 14 character string. Normally leading with 2 alpha characters ('EP', 'MV', 'SH' or 'SP'), followed by 12 numbers. |
The TMS ID will be a 14 character string. Normally being with 'EV,' 'EP', 'SH', 'SP', or 'MV' Followed by 12 numbers after the initial two letter prefix. The Giant Morning Show: SH009311820022 The Pants Alternative Episode : EP009311820061 |
Optional | Nielsen |
crossId2 | Populated by content distributor to contribute viewing from that distributor to the given content originator. | For a full list of acceptable values, please contact your Nielsen reprentative. | Yes, for distributors | Nielsen |
length | Length of content in seconds Note: Integers and decimals are acceptable values are acceptable for the length parameter. |
Examples:
For standard VOD content - |
Yes | Client |
airdate | Original broadcast or release date for the program For USA, date should be EST Outside USA, date should be local time. If not applicable or available, original broadcast or release date for the Program. |
Acceptable Formats:YYYY-MM-DDTHH:MI:SS YYYY-MM-DDHH:MI:SS YYYY-MM-DDTHH:MI:SS+xx:xx YYYY-MM-DDTHH:MI:SS-xx:xx YYYYMMDDHH:MI:SS YYYYMMDD HH:MI:SS MM-DD-YYYY MM/DD/YYYY YYYYMMDD |
Yes | Client |
isfullepisode | Full episode flag to identify differences between long form content. | y - full episode, n - non full episode(clip,teaser,promo,etc.)
Also accept:
|
Yes | Nielsen |
adloadtype | Type of ad load:
|
2 - DCR measures content with dynamic ads |
Yes | Nielsen |
segB | One of two custom segment for the clients granular reporting within a brand. | Examples: Genre - horror , comedy , etc.Timeslot - primetime , daytime , etc.News type - breakingnews , weather , etc. |
Optional | Client |
segC | One of two custom segment for the clients granular reporting within a brand. | Examples: Genre - horror , comedy , etc.Timeslot - primetime , daytime , etc.News type - breakingnews , weather , etc. |
Optional | Client |
Custom segments (segB and segC) can be used to aggregate video and/or static content within a single Brand to receive more granular reports within a brand.
Examples regarding usage of segments within SDK:
- All comedy clips and stories for a Brand rolled into a "Comedy" segment
- genre grouping content by Comedy vs. Drama
- group related Text + Video content - i.e. for a show that has a lot of - static pages associated with it
- packaging based on how clients sell inventory
- grouping related types of content either by genre, category or platform.
Metadata Example
Swift
let contentMetadata = [
"type": "content",
"assetid": "C77664",
"program": "The Big Bang Theory",
"title": "The Pants Alternative S03E18", //Formats accepted: S01E03, S1E3, S1 E3
"crossId1": "EP009311820061", //optional
"crossId2": "Content Originator", //optional
"length": "3600",
"airdate": "2022-03-21T10:05:00",
"isfullepisode": "Yes",
"adloadtype": "2",
"segB": "CustomSegmentValueB", //optional
"segC": "CustomSegmentValueC" //optional
];
Objective-C
NSDictionary * contentMetadata = @ {
@ "type": @ "content",
@ "assetid": @ "C77664",
@ "program": @ "The Big Bang Theory",
@ "title": @ "The Pants Alternative S03E18", //Formats accepted: S01E03, S1E3, S1 E3
@ "crossId1": @ "EP009311820061", //optional
@ "crossId2": @ "Content Originator", //optional
@ "length": @ "3600",
@ "airdate": @ "2022-03-21T10:05:00",
@ "isfullepisode": @ "y",
@ "adloadtype": @ "2",
@ "segB": @ "CustomSegmentValueB", //optional
@ "segC": @ "CustomSegmentValueC" //optional
}
iOS DCR Video Step 4 - Basic Set of Events - Sample Playback
Show/hide step 4
SDK Events
Event | Parameter | Description |
---|---|---|
'play' | Call at start of each new stream | |
'loadMetadata' | content/ad metadata object | Needs to be called at the beginning of each asset |
'playheadPosition' | playhead position as integer VOD: current position in seconds |
Pass playhead position every second during playback |
'stop' | playhead position | Call during any interruption to content or Ad playback and at the end of each Ad. |
'end' | playhead position in seconds | Call when the current video asset completes playback and pass the playhead position. Example: At the end of the content stream, if the user switches to another piece of content, when the browser is refreshed or closed. |
Note: For livestream, send the UNIX timestamp, for VOD send the time in seconds as integer. The final playhead position must be sent for the current asset being played before calling
stop
,end
orloadmetadata
,.
Life cycle of SDK instance
Life cycle of SDK instance includes four general states:
- Initial state – The SDK is not initialized and hence, not ready to process playing information. Once the SDK is moved out of this state, it needs instantiation of the new SDK instance in order to get the instance in the Idle state.
- Idle state – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for an event to occur.
- Processing state – The SDK instance is processing playing information. The
play
andloadMetadata
calls move the SDK instance into this state. In this state, the SDK instance will be able to process the following calls.playheadPosition
– Call this API every one second when playhead position is active. If a LIVE event, use the current UNIX timestamp (seconds since Jan-1-1970 UTC).stop
– Call this API when the content or Ad playback is interrupted and at the end of each Ad.end
– Call when content completes. When called, the SDK instance exits from Processing state.
- Disabled state – The SDK instance is disabled and is not processing playing information.
appDisableApi
is set totrue
Note: For API Version 5.1 and above, App SDK will fire data pings and continue measurement even after the user has opted out from Nielsen measurement on a device. The data ping will be marked as opted-out ping.
Note: In case of any interruptions during playback due to alarm, calendar, call, flight mode, Wi-Fi toggle, channel change, etc., call stop to stop the measurement.
- As soon as the playback resumes, call
loadMetadata
andplayheadPosition
API Call Sequence
Sample Use Case: Content has no Advertisements
Call play() at start of stream
Call loadMetadata() with JSON metadata for content as below.
{
"type": "content",
"assetid": "vid345-67483",
"program": "ProgramName",
"title": "Program S3, EP1",
"length": "3600",
...
}
Call playheadPosition() every one second until a pause / stop. Use the sample API sequence below as a reference to identify the specific events that need to be called during content playback without ads.
Type | Sample code | Description |
---|---|---|
Start of stream | mAppSdk.play(); |
// Call at start of each new stream |
mAppSdk.loadMetadata(contentMetaDataObject); |
// contentMetadataObject contains the JSON metadata for the content being played | |
Content | mAppSdk.setPlayheadPosition(playheadPosition); |
// position is position of the playhead while the content is being played |
Interruption | mAppSdk.stop(); |
// call stop when content playback is interrupted |
Resume Content | mAppSdk.loadMetadata(contentMetaDataObject); |
// Call loadMetadata and pass content metadata object when content resumes |
mAppSdk.setPlayheadPosition(playheadPosition); |
// continue pasing playhead position every second starting from position where content is resumed | |
End of Stream | mAppSdk.end(); |
// Content playback is completed. |
Keep Going
Show/hide
Congratulations, you've successfully integrated the iOS SDK in your app for a basic content playback scenario!
You can add more content to see channel-change scenarios or continue to next steps below.
View your application's debug logs and search for the term (AppSDK) to see messages emitted by Nielsen AppSDK during video playback.
Next Steps
Show/hide
Going Live
In addition to the basic steps above, before going live developers need to handle app background/foreground events, make certain privacy disclosures, handle interruption events (stop, fast-forward, rewind), remove iOS simulator slices, and allow users to opt out of Nielsen measurement. More details can be found here, along with a more comprehensive reference for implementing DCR Video measurement with AppSDK.
Once the DCR Tracking Code is added, Nielsen will validate the implementation. Following Nielsen testing, developers need to make a few updates to the initialization call to ensure that the app is being measured properly.
- App ID: Ensure that correct is used during initialization PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
- Debug Logging: Disable logging by changing initialization call to use @"nol_devDebug":@"INFO".
→ iOS DTVR
Show/hide iOS DTVR
iOS DTVR Introduction
Show/hide Intro
The Nielsen DTVR (Digital TV Ratings) product provides content consumption measurement in client mobile apps and webpages. This measurement includes insight into the total time a user spent watching the tracked content, video player events, and much more. This example provides the steps to implement the DTVR product in a sample iOS app using Nielsen AppSDK. It includes:
- SDK Initialization
- DTVR Video Metadata: information about the content being tracked
- DTVR Video Events/API calls
By the end of this guide you will have the needed steps to integrate Nielsen's AppSDK in the background of your app for DTVR measurement.
NOTE: video streams must have Nielsen ID3 tags embedded in order to be measured using the DTVR product. See Retrieving_ID3_Tags or contact your Nielsen representative for more information.
iOS DTVR Step 1 - Obtain AppID
Show/hide step 1
To begin using the iOS AppSDK, you will need to obtain an Application ID (AppId)
Item | Description | Source | |
---|---|---|---|
✅ | App ID (appid) | Unique ID assigned to the player/site and configured by product | Contact your Nielsen Representative |
The appid is a 37 character unique ID assigned to the player/site and configured by product and is required when creating a new instance of the AppSDK in the app.
Example: PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXX
iOS DTVR Step 2 - SDK Initialization
Show/hide step 2
How to obtain the NielsenAppApi.Framework
The Nielsen AppSDK can either be downloaded directly or can be integrated directly within an application through the use of CocoaPods. We recommend using the CocoaPods-based integration whenever possible to ensure you maintain the most recent changes and enhancements to the Nielsen libraries.
Configuring Xcode Development Environment
Starting with SDK version 6.0.0.0, the Nielsen App SDK is compatible with Apple iOS versions 8.0 and above. In addition, when using the dynamic framework, all the required frameworks are linked automatically as the are needed. More details can be found here: https://stackoverflow.com/questions/24902787/dont-we-need-to-link-framework-to-xcode-project-anymore
Note: All communications between the SDK and the Census (Collection Facility) use HTTPS.
= Download Framework =
The first step is to download and copy the NielsenAppApi.framework bundle to the app project directory. (Not required if using CocaPods)
= Add Framework =
In the General tab for app configuration add NielsenAppApi.framework in the list of Embedded Binaries. (Not required if using CocaPods)
= Add Path =
Add path to the NielsenAppApi.framework in the Framework Search Paths build setting. (Not required if using CocaPods)
= Import Framework =
Add NielsenAppApi.framework module in the source file of your app:
= Using Swift =
Add the following:
import NielsenAppApi
= Using Objective-C =
@import NielsenAppApi;
= SDK Initialization =
The following table contains the list of arguments that can be passed via the AppInfo JSON schema.
Parameter / Argument | Description | Source | Required? | Example |
---|---|---|---|---|
appid | Unique Nielsen ID for the application. The ID is a GUID data type. If you did not receive your App ID, let us know and we will provide you. | Nielsen-specified | Yes | PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX |
nol_devDebug | Enables Nielsen console logging. Only required for testing |
Nielsen-specified | Optional | DEBUG |
Debug flag for development environment
Player application developers / integrators can use Debug flag to check whether an App SDK API call made is successful. To activate the Debug flag,
Pass the argument @"nol_devDebug":@"DEBUG"
, in the JSON string .
Once the flag is active, it logs each API call made and the data passed. The log created by this flag is minimal.
Note: DO NOT activate the Debug flag in a production environment.
Swift Example
Sample SDK Initialization Code
NielsenInit.swift
class NielsenInit: NSObject {
class func createNielsenAppApi(delegate: NielsenAppApiDelegate) -> NielsenAppApi?{
let appInformation:[String: String] = [
"appid": "PE392366B-F2C1-4BC4-AB62-A7DAFDCXXXX",
"nol_devDebug": "DEBUG"
]
return NielsenAppApi(appInfo:appInformation, delegate:delegate)}}
ViewController.swift
class ViewController: UIViewController, NielsenAppApiDelegate, AVPictureInPictureControllerDelegate, CLLocationManagerDelegate {
let avPlayerViewController = AVPlayerViewController()
var avPlayer:AVPlayer?
var nielsenAppApi: NielsenAppApi!
override func viewDidLoad() {
super.viewDidLoad()
self.nielsenAppApi = NielsenInit.createNielsenAppApi(delegate: self)
NSLog("Nielsen SDK initialized")
}}
Objective C
Sample SDK Initialization Code
Initialize the Nielsen App object within the viewDidLoad view controller delegate method using initWithAppInfo:delegate:
If App SDK is initialized using init or new methods, it will ignore the API calls resulting in no measurement. The SDK will not return any errors.
#import "NlsAppApiFactory.h"
#import <NielsenAppApi/NielsenAppApi.h>
@implementation NlsAppApiFactory
+ (NielsenAppApi *)createNielsenAppApiWithDelegate:(id<NielsenAppApiDelegate>)delegate;
{
NSDictionary *appInformation = @{
@"appid": "PE392366B-F2C1-4BC4-AB62-A7DAFDC51XXX",
@"nol_devDebug": @"DEBUG"
};
return [[NielsenAppApi alloc] initWithAppInfo:appInformation delegate:delegate];
}
@end
The following would be the NlsAppApiFactory.h
file:
#import <Foundation/Foundation.h>
@class NielsenAppApi;
@protocol NielsenAppApiDeligate;
@interface NlsAppApiFactory : NSObject
+ (NielsenAppAPI *) createNielsenAppApiWithDelegate:(id<NielsenAppApiDelegate>)delegate;
@end
}}
The following might be in the Viewcontroller.m
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//Setting background image
UIImage *backgroundImage = [UIImage imageNamed:@"new_ios_bg.png"];
UIImageView *backgroundImageView=[[UIImageView alloc]initWithFrame:self.view.frame];
backgroundImageView.image=backgroundImage;
[self.view insertSubview:backgroundImageView atIndex:0];
//Mark: In NielsenInit class we are initialising the Nielsen SDK.
//Getting the instance of Nielsen SDK
nielsenApi = [NielsenInit createNielsenAppApiWithDelegate:nil];
}
iOS DTVR Step 3 - Create DTVR Content Metadata Object
Show/hide step 3
Configure Metadata
Content metadata should remain constant throughout the completion of an episode or live stream.
Key | Description | Values | Required |
---|---|---|---|
type | type of asset | "content" | |
adModel | linear vs dynamic ad model | 1 = Linear matches TV ad load for DTVR | ✓ |
- (NSDictionary *)loadDtvr{
//Loading DTVR data
NSDictionary *dtvr = @{ @"adModel":@"1" ,
@"type":@"content",};
return dtvr;
}
iOS DTVR Step 4 - Basic Set of Events - Sample Playback
Show/hide step 4
SDK Events/APIs
Event | Parameter | Description |
---|---|---|
'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 |
Configure API calls - loadMetadata
Use loadMetadata
to pass the metadata object created above.
Swift
self.nielsenAppApi?.loadMetadata(dtvr)
Objective C
[nielsenApi loadMetadata:(dtvr)];
Configure API calls - sendID3
sendID3 API is a Nielsen AppSDK receiver for timed metadata events (ID3 tags) provided through iOS’s NSNotificationCenter notification system. This API filters out Nielsen-specific ID3 tags from the system and uses them to create duration data. These ID3 tags are used by Nielsen SDK for DTVR measurement, and the stream that is played must contain ID3 tags and have these tags extracted and passed to SDK using the below procedure in order for DTVR measurement to occur.
Swift
[nielsenApi sendID3:extraString];
Objective C
[nielsenApi sendID3:extraString];
Sample ID3 tags
www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/X100zdCIGeIlgZnkYj6UvQ==/AAAB2Jz2_k74GXSzx4npHuI_
JwJd3QSUpW30rDkGTcbHEzIMWleCzM-uvNOP9fzJcQMWQLJqzXMCAxParOb5sGijSV9dNM3QiBniJYGZ5GI-lL1fXTTN0IgZ4iWBmeRiPpS9AAAAAAAAAAAAAAAAAAAAAFJWFM5SVhTONNU=/00000/00000/00 www.nielsen.com/X100zdCIGeIlgZnkYj6UvQ==/R8WHe7pEBeqBhu8jTeXydg==/AAICoyitYqlxT7n6aZ0oMCGhe
Fi4CXFp46AMUPZz1lMr_M9tr3_cjee1SHqxrOiVerMDLeyn9xzocZSKwi746Re8vNOtpNCAZjYABs_J0R25IHpvOc1HS8 QHGgD5TgOJeS6gX100zdCIGeIlgZnkYj6UvVJWFNhSVhTiPE0=/00000/46016/00
Refer to Retrieving ID3 Tags section to know more details.
Retrieving ID3 Tags
ID3 tags have a payload of about 249 characters and start with "www.nielsen.com".
As Apple has deprecated the use of timedMetadata, we now recommend using AVPlayerItemMetadataOutput for extracting ID3 tags from the iOS Native Player.
If any other player apart from the iOS native player is used, check and ensure that the player has the capability to extract metadata such as ID3 tags.
Examples of extracting ID3 tags from the iOS Native Player
Swift
//First, ensure your class conforms to the AVPlayerItemMetadataOutputPushDelegate protocol.
class YourClass: AVPlayerItemMetadataOutputPushDelegate {
}
// Then create an instance of AVPlayerItemMetadataOutput and add it to the player item
let metadataOutput = AVPlayerItemMetadataOutput(identifiers: nil)
playerItem.add(metadataOutput)
// and set the delegate and a dispatch queue
metadataOutput.setDelegate(self, queue: DispatchQueue.main)
// After that below callback function of AVPlayerItemMetadataOutputPushDelegate
// protocol will be triggered whenever ID3 tag is received from stream.
func metadataOutput(_ output: AVPlayerItemMetadataOutput, didOutputTimedMetadataGroups groups: [AVTimedMetadataGroup], from track: AVPlayerItemTrack?) {
for group in groups {
for item in group.items {
// Handle the metadata item
handleTimedMetadata(metadataItem: item)
}
}
}
// Then further metadata item can be handled like below
func handleTimedMetadata(metadataItem: AVMetadataItem) {
guard let key = metadataItem.key as? String,
let extraString = metadataItem.extraAttributes?[AVMetadataExtraAttributeInfoKey] as? String else {
return
}
// If the extra string(tag) starts with "www.nielsen.com", then only sending to SDK
if key == "PRIV" && extraString.hasPrefix("www.nielsen.com") {
DispatchQueue.global(qos: .default).async {
self.nielsenApi?.sendID3(extraString)
}
}
}
Objective C
//First, ensure your class conforms to the AVPlayerItemMetadataOutputPushDelegate protocol.
@interface YourClass : NSObject <AVPlayerItemMetadataOutputPushDelegate>
@end
// Then create an instance of AVPlayerItemMetadataOutput and add it to the player item
AVPlayerItemMetadataOutput *metadataOutput = [[AVPlayerItemMetadataOutput alloc] initWithIdentifiers:nil];
[playerItem addOutput:metadataOutput];
// and set the delegate and a dispatch queue
[metadataOutput setDelegate:self queue:dispatch_get_main_queue()];
// After that below callback function of AVPlayerItemMetadataOutputPushDelegate
// protocol will be triggered whenever ID3 tag is received from stream.
- (void)metadataOutput:(AVPlayerItemMetadataOutput *)output didOutputTimedMetadataGroups:(NSArray<AVTimedMetadataGroup *> *)groups fromPlayerItemTrack:(AVPlayerItemTrack *)track {
for (AVTimedMetadataGroup *group in groups) {
for (AVMetadataItem *item in group.items) {
// Handle the metadata item
[self handleTimedMetadata:item];
}
}
}
// Then further metadata item can be handled like below
- (void)handleTimedMetadata:(AVMetadataItem *)item {
NSString *key = (NSString *)item.key;
NSString *extraString = item.extraAttributes[AVMetadataExtraAttributeInfoKey];
// If the key is "PRIV" and the extra string starts with "www.nielsen.com", send it to the Nielsen API
if ([key isEqualToString:@"PRIV"] && [extraString hasPrefix:@"www.nielsen.com"]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.nielsenApi sendID3:extraString];
});
}
}
Life cycle of SDK instance
Life cycle of SDK instance includes four general states:
- Initial state – The SDK is not initialized and hence, not ready to process playing information.
- Idle state – The SDK is initialized and is ready to process playing information. Once Initialized, the SDK instance is not processing any data, but is listening for the loadMetadata and sendID3 events to occur.
- Processing state – The SDK instance is processing playing information. For DTVR, the
loadMetadata
call moves the SDK instance into this state. In this state, the SDK instance will be able to process sendID3 calls and measure content. - Disabled state – The SDK instance is disabled.
Keep Going
Show/hide
Congratulations, you've successfully integrated the iOS SDK in your app for a basic content playback scenario!
You can add more content to see channel-change scenarios or continue to next steps below.
View your application's debug logs and search for the term (AppSDK) to see messages emitted by Nielsen AppSDK during video playback.
Next Steps
Show/hide
Going Live
In addition to the basic steps above, before going live developers need to handle app background/foreground events, make certain privacy disclosures, handle interruption events (stop, fast-forward, rewind), remove iOS simulator slices, and allow users to opt out of Nielsen measurement. More details can be found here, along with a more comprehensive reference for implementing DTVR measurement with AppSDK.
Once the DTVR Tracking Code is added, Nielsen will validate the implementation. Following Nielsen testing, developers need to make a few updates to the initialization call to ensure that the app is being measured properly.
- App ID: Ensure that correct is used during initialization PXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
- Debug Logging: Disable logging by changing initialization call to use @"nol_devDebug":@"INFO".