Template

Difference between revisions of "iOS Privacy and Opt-Out"

From Engineering Client Portal

(Legacy Opt-out example code)
(Privacy and Opt-Out)
Line 16: Line 16:
 
*  If the User's device is running < iOS 13.x, the Nielsen SDK will check the status of '''Limit Ad Tracking'''.
 
*  If the User's device is running < iOS 13.x, the Nielsen SDK will check the status of '''Limit Ad Tracking'''.
 
*  iOS14 modifies the way Apple manages the collection of a User's Opt-In status through '''AppTracking'''. Starting with Version 8.x+, the Nielsen App SDK will check the iOS version during initialization. If the device is running iOS12 or iOS13, the Limit Ad Tracking setting is requested. If iOS14.x +, then AppTracking is utilized.
 
*  iOS14 modifies the way Apple manages the collection of a User's Opt-In status through '''AppTracking'''. Starting with Version 8.x+, the Nielsen App SDK will check the iOS version during initialization. If the device is running iOS12 or iOS13, the Limit Ad Tracking setting is requested. If iOS14.x +, then AppTracking is utilized.
 
+
<!--
 
==== Webview Example  ====
 
==== Webview Example  ====
 
The below code is an example of displaying the Nielsen Privacy page to the user.
 
The below code is an example of displaying the Nielsen Privacy page to the user.
Line 47: Line 47:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
<br>
 
<br>
 
+
-->
 
=== User Choice ===
 
=== User Choice ===
 
The ''User Choice'' method can be used without the Ad Framework, or in situations where the publisher does not wish to use the [https://developer.apple.com/documentation/apptrackingtransparency App Tracking Transparency Framework].
 
The ''User Choice'' method can be used without the Ad Framework, or in situations where the publisher does not wish to use the [https://developer.apple.com/documentation/apptrackingtransparency App Tracking Transparency Framework].
Line 61: Line 61:
  
 
==== Opt-out example code ====
 
==== Opt-out example code ====
 +
===== Swift =====
 +
<syntaxhighlight lang="swift">
 +
import UIKit
 +
import WebKit
 +
import NielsenAppApi
 +
 +
class OptOutVC: UIViewController, NielsenAppApiDelegate, WKNavigationDelegate {
 +
    var nielsenApi : NielsenAppApi!
 +
    var webView: WKWebView!
 +
 
 +
    override func loadView() {
 +
        webView = WKWebView()
 +
        webView.navigationDelegate = self
 +
        view = webView
 +
    }
 +
 +
    override func viewDidLoad() {
 +
        super.viewDidLoad()
 +
 +
        if let appApi = self.nielsenApi {
 +
            //Getting the optPut URL from SDK
 +
            if let url = URL(string: appApi.optOutURL) {
 +
                webView.load(URLRequest(url: url))
 +
                webView.allowsBackForwardNavigationGestures = true
 +
            }}}
 +
 +
        func closeOptOutView() {
 +
            self.dismiss(animated: true, completion: nil)
 +
        }
 +
 
 +
// Uncomment below code if you are using User Choice.  This will receive the user's selection
 +
// From the custom User_Choice opt out page.  Only required for non-ad framework or no-id builds
 +
// of the Nielsen SDK
 +
/* 
 +
        func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler:
 +
@escaping (WKNavigationActionPolicy) -> Void) {
 +
            print(navigationAction.request.url?.absoluteString as Any) //For debugging to check what is being passed from webpage.
 +
            if navigationAction.request.url?.absoluteString == "nielsen://close" {
 +
                closeOptOutView()
 +
                decisionHandler(.cancel)
 +
            } else {
 +
                if let url = navigationAction.request.url?.absoluteString, url.hasPrefix("nielsen") {
 +
                    nielsenApi?.userOptOut(url). //either nielsenappsdk://1 or nielsenappsdk://0
 +
                    decisionHandler(.cancel)
 +
                } else {
 +
                    if navigationAction.navigationType == .linkActivated {
 +
                        if let url = navigationAction.request.url?.absoluteString, url.hasSuffix("#") {
 +
                            decisionHandler(.allow)
 +
                        } else {
 +
                            decisionHandler(.cancel)
 +
                            webView.load(navigationAction.request)
 +
                        }
 +
                    } else {
 +
                        decisionHandler(.allow)
 +
                    }}}}
 +
  */
 +
}
 +
 +
</syntaxhighlight>
 
===== Objective-C =====
 
===== Objective-C =====
 
  <syntaxhighlight lang="objective-c">
 
  <syntaxhighlight lang="objective-c">
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)
 
navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
 
  
    NSURLRequest *request = [navigationAction request];
+
#import "OptOutVC.h"
    NSString *url = [[request URL]absoluteString];
+
#import "NielsenInit.h"
   
+
#import <NielsenAppApi/NielsenAppApi.h>
    if([url isEqualToString:self.NIELSEN_URL_OPT_OUT] || [url isEqualToString:self.NIELSEN_URL_OPT_IN]){
+
 
        [self.nielsenApi userOptOut:url];
+
@interface OptOutVC ()
        decisionHandler(WKNavigationActionPolicyAllow);
+
 
    }else{
+
@property (weak, nonatomic) IBOutlet UIWebView *webView;
        decisionHandler(WKNavigationActionPolicyCancel);
+
@end
    }       
 
}
 
</syntaxhighlight>
 
===== Swift =====
 
<syntaxhighlight lang="swift">
 
  
var webView: WKWebView!
+
@implementation OptOutVC
var NIELSEN_URL_OPT_OUT : String = "nielsenappsdk://1"
 
var NIELSEN_URL_OPT_IN : String = "nielsenappsdk://0"
 
  
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction,
+
- (void)viewDidLoad {
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
+
    [super viewDidLoad];
  
      let urlStr = navigationAction.request.url?.absoluteString
+
- (void)viewDidLoad {
 +
    [super viewDidLoad];
 +
    //Getting the optPut URL from eventTracker
 +
    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL
 +
URLWithString:self.nielsenApi.optOutURL]]];
 +
}
  
         if(urlStr == NIELSEN_URL_OPT_OUT || urlStr == NIELSEN_URL_OPT_IN){
+
// Uncomment below code if you are using User Choice.  This will receive the user's selection
             let appApi = self.nielsenApi
+
// From the custom User_Choice opt out page.  Only required for non-ad framework or no-id builds
             appApi?.userOptOut(urlStr)
+
// of the Nielsen SDK
            decisionHandler(.allow)
+
/*   
 +
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
 +
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
 +
{
 +
    if ([navigationAction.request.URL.absoluteString isEqualToString:kNielsenWebClose])
 +
    {  [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];
 +
        decisionHandler(WKNavigationActionPolicyCancel);
 +
    } else {
 +
         if ([navigationAction.request.URL.absoluteString hasPrefix:@"nielsen"])
 +
        {[self.nielsenAppApi userOptOut:navigationAction.request.URL.absoluteString];
 +
            decisionHandler(WKNavigationActionPolicyCancel);
 +
        } else {
 +
             if (navigationAction.navigationType == WKNavigationTypeLinkActivated)
 +
             { if ([navigationAction.request.URL.absoluteString hasSuffix:@"#"])
 +
                      {decisionHandler(WKNavigationActionPolicyAllow);
 +
                } else {
 +
                    decisionHandler(WKNavigationActionPolicyCancel);
 +
                    [webView loadRequest:[NSURLRequest requestWithURL:navigationAction.request.URL]];
 +
                }} else {
 +
                decisionHandler(WKNavigationActionPolicyAllow);
 +
            }}}
 +
*/
 +
}
  
        }else{
 
          decisionHandler(.cancel)
 
        }
 
    }
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
=== Retrieve current Opt-Out preference ===
 
=== Retrieve current Opt-Out preference ===
 
Whether the user is opted out via OS-level Opt-out or via User Choice Opt-out, the current Opt-Out status as detected by the SDK is available via the [[optOutStatus]] property in the Nielsen SDK API
 
Whether the user is opted out via OS-level Opt-out or via User Choice Opt-out, the current Opt-Out status as detected by the SDK is available via the [[optOutStatus]] property in the Nielsen SDK API
 +
<syntaxhighlight lang="Swift">
 +
print("Optout status is", nielsenApi.optOutStatus) // example of printing optout status to the console.
 +
</syntaxhighlight>
  
 
=== Required Privacy Links ===
 
=== Required Privacy Links ===

Revision as of 22:10, 28 June 2021

Privacy and Opt-Out

There are two primary methods for implementing user Opt-out preferences:

  1. OS-level Opt-out - managed by AppTracking or Limit Ad Tracking setting on device (preferred approach).
  2. User Choice - Direct call to SDK. Can be used without the Ad Framework

Special Note Regarding Apps in the Kids Category

If you are building an app that will be listed in the Kids Category:

  1. Ensure that you are using the NoID version of the Nielsen SDK Framework.
  2. Immediately following the initialization of the Nielsen SDK ensure you call the userOptOut API with Opt out selection:
NielsenAppApi?.userOptOut("nielsenappsdk://1"); // User opt-out

OS-level Opt-out

OS-level Opt-out method available on Nielsen iOS

The Nielsen SDK automatically leverages the iOS's Limit Ad Tracking or AppTracking setting.

  • If the User's device is running < iOS 13.x, the Nielsen SDK will check the status of Limit Ad Tracking.
  • iOS14 modifies the way Apple manages the collection of a User's Opt-In status through AppTracking. Starting with Version 8.x+, the Nielsen App SDK will check the iOS version during initialization. If the device is running iOS12 or iOS13, the Limit Ad Tracking setting is requested. If iOS14.x +, then AppTracking is utilized.

User Choice

The User Choice method can be used without the Ad Framework, or in situations where the publisher does not wish to use the App Tracking Transparency Framework.

The User Choice opt-out method works as follows:

  • Get the Nielsen opt-out URL via optOutURL
  • Display a WebView element whose loadUrl is set to the value obtained from optOutURL
  • Detect if the WebView URL changes to a special URL that indicates Opt-in, or Opt-out and close the WebView
    • Opt-out if the WebView URL = nielsenappsdk://1
    • Opt-in if the WebView URL = nielsenappsdk://0
  • Pass the detected URL to the userOptOut function
    • Example:
      NielsenAppApi?.userOptOut("nielsenappsdk://1"); // User opt-out
      

Opt-out example code

Swift
import UIKit
import WebKit
import NielsenAppApi

class OptOutVC: UIViewController, NielsenAppApiDelegate, WKNavigationDelegate {
    var nielsenApi : NielsenAppApi!
    var webView: WKWebView!
   
    override func loadView() {
        webView = WKWebView()
        webView.navigationDelegate = self
        view = webView
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        if let appApi = self.nielsenApi {
            //Getting the optPut URL from SDK
            if let url = URL(string: appApi.optOutURL) {
                webView.load(URLRequest(url: url))
                webView.allowsBackForwardNavigationGestures = true
            }}}

        func closeOptOutView() {
            self.dismiss(animated: true, completion: nil)
        }
  
// Uncomment below code if you are using User Choice.  This will receive the user's selection
// From the custom User_Choice opt out page.  Only required for non-ad framework or no-id builds
// of the Nielsen SDK
/*  
        func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: 
@escaping (WKNavigationActionPolicy) -> Void) {
            print(navigationAction.request.url?.absoluteString as Any) //For debugging to check what is being passed from webpage.
            if navigationAction.request.url?.absoluteString == "nielsen://close" {
                closeOptOutView()
                decisionHandler(.cancel)
            } else {
                if let url = navigationAction.request.url?.absoluteString, url.hasPrefix("nielsen") {
                    nielsenApi?.userOptOut(url). //either nielsenappsdk://1 or nielsenappsdk://0
                    decisionHandler(.cancel)
                } else {
                    if navigationAction.navigationType == .linkActivated {
                        if let url = navigationAction.request.url?.absoluteString, url.hasSuffix("#") {
                            decisionHandler(.allow)
                        } else {
                            decisionHandler(.cancel)
                            webView.load(navigationAction.request)
                        }
                    } else {
                        decisionHandler(.allow)
                    }}}}
  */
}
Objective-C
#import "OptOutVC.h"
#import "NielsenInit.h"
#import <NielsenAppApi/NielsenAppApi.h>

@interface OptOutVC ()

@property (weak, nonatomic) IBOutlet UIWebView *webView;
@end

@implementation OptOutVC

- (void)viewDidLoad {
    [super viewDidLoad];

- (void)viewDidLoad {
    [super viewDidLoad];
    //Getting the optPut URL from eventTracker
    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL
 URLWithString:self.nielsenApi.optOutURL]]];
}

// Uncomment below code if you are using User Choice.  This will receive the user's selection
// From the custom User_Choice opt out page.  Only required for non-ad framework or no-id builds
// of the Nielsen SDK
/*     
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
 decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    if ([navigationAction.request.URL.absoluteString isEqualToString:kNielsenWebClose])
    {   [self performSelector:@selector(closeOptOutView) withObject:nil afterDelay:0];
        decisionHandler(WKNavigationActionPolicyCancel); 
     } else {
        if ([navigationAction.request.URL.absoluteString hasPrefix:@"nielsen"])
        {[self.nielsenAppApi userOptOut:navigationAction.request.URL.absoluteString];
            decisionHandler(WKNavigationActionPolicyCancel); 
        } else {
            if (navigationAction.navigationType == WKNavigationTypeLinkActivated) 
            { if ([navigationAction.request.URL.absoluteString hasSuffix:@"#"]) 
                      {decisionHandler(WKNavigationActionPolicyAllow);
                } else {
                    decisionHandler(WKNavigationActionPolicyCancel);
                    [webView loadRequest:[NSURLRequest requestWithURL:navigationAction.request.URL]];
                }} else {
                 decisionHandler(WKNavigationActionPolicyAllow);
            }}}
*/
}

Retrieve current Opt-Out preference

Whether the user is opted out via OS-level Opt-out or via User Choice Opt-out, the current Opt-Out status as detected by the SDK is available via the optOutStatus property in the Nielsen SDK API

 print("Optout status is", nielsenApi.optOutStatus) // example of printing optout status to the console.

Required Privacy Links

Users must either have access to the "About Nielsen Measurement" page, or have similar text available within the native app. Include "About Nielsen Measurement" and "Your Choices" link in the Privacy Policy / EULA or as a button near the link to the app's Privacy Policy.

In addition, the following text must be included in your app store description.

"Please note: This app features Nielsen’s proprietary measurement software which contributes to market research, like Nielsen’s TV Ratings. Please see https://www.nielsen.com/us/en/legal/privacy-statement/digital-measurement/ for more information"