שנתחיל?

בהתאם למדיניות Google בנושא הסכמת משתמשים באיחוד האירופי, עליך להציג הודעות גילוי נאות מסוימות למשתמשים שנמצאים באזור הכלכלי האירופי (EEA) ובבריטניה. בנוסף, עליך לקבל את הסכמתם לשימוש בקובצי cookie או באמצעים אחרים לאחסון מקומי, כשהדבר נדרש על פי חוק, וכדי להשתמש במידע אישי (כמו מזהה פרסום) לצורך הצגת מודעות. המדיניות הזו משקפת את הדרישות שמפורטות ב-ePrivacy Directive (ההנחיה בנושא פרטיות ותקשורת אלקטרונית) וב-General Data Protection Regulation (התקנה הכללית להגנה על מידע, GDPR) של האיחוד האירופי.

כדי לעזור לבעלי אפליקציות למלא את החובות שלהם במסגרת המדיניות הזו, Google מציעה את ה-User Messaging Platform (UMP) SDK. ה-UMP SDK עודכן כדי לתמוך בתקנים האחרונים של IAB. עכשיו אפשר לטפל בכל ההגדרות האלה בנוחות AdMob בפרטיות ובהעברת הודעות.

דרישות מוקדמות

יצירת סוג הודעה

אפשר ליצור הודעות למשתמשים באמצעות אחד הסוגים הזמינים של הודעות למשתמשים בכרטיסייה פרטיות והודעות בחשבון AdMob שלך. ה-UMP SDK מנסה להציג הודעת משתמש שנוצרה מ AdMob מזהה האפליקציה שהוגדר בפרויקט. אם לא מוגדרת הודעה לאפליקציה, ה-SDK יחזיר שגיאה.

לפרטים נוספים קראו את המאמר מידע על פרטיות והעברת הודעות.

ייבוא ה-SDK

CocoaPods (מועדף)

הדרך הקלה ביותר לייבא את ה-SDK לפרויקט ל-iOS היא באמצעות CocoaPods. פותחים את קובץ ה-Podfile של הפרויקט ומוסיפים את השורה הבאה ליעד של האפליקציה:

pod 'GoogleUserMessagingPlatform'

לאחר מכן, מריצים את הפקודה הבאה:

pod install --repo-update

אם זו הפעם הראשונה שאתם משתמשים ב-CocoaPods, קראו את המאמר שימוש ב-CocoaPods כדי להבין איך ליצור קובצי Podfiles ולהשתמש בהם.

הורדה ידנית

הדרך השנייה לייבוא ה-SDK היא לעשות זאת באופן ידני.

הורדת ה-SDK

לאחר מכן גוררים את ה-framework לפרויקט Xcode, ומקפידים לבחור באפשרות Copy items if need (העתקת פריטים במידת הצורך).

לאחר מכן אפשר לכלול את ה-framework בכל קובץ הדרוש לכם באמצעות:

Swift

import UserMessagingPlatform

Objective-C

#include <UserMessagingPlatform/UserMessagingPlatform.h>

צריך לבקש עדכון של פרטי ההסכמה של המשתמש בכל השקה של אפליקציה, באמצעות requestConsentInfoUpdateWithParameters:completionHandler:. כך תקבעו אם המשתמש צריך להביע הסכמה אם הוא לא עשה זאת עדיין, או אם פג התוקף של ההסכמה שלו.

דוגמה לבדיקת הסטטוס של UIViewController בשיטה viewDidLoad().

Swift

override func viewDidLoad() {
  super.viewDidLoad()

  // Create a UMPRequestParameters object.
  let parameters = UMPRequestParameters()
  // Set tag for under age of consent. false means users are not under age
  // of consent.
  parameters.tagForUnderAgeOfConsent = false

  // Request an update for the consent information.
  UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: parameters) {
    [weak self] requestConsentError in
    guard let self else { return }

    if let consentError = requestConsentError {
      // Consent gathering failed.
      return print("Error: \(consentError.localizedDescription)")
    }

    // TODO: Load and present the consent form.
  }
}

Objective-C

- (void)viewDidLoad {
  [super viewDidLoad];

  // Create a UMPRequestParameters object.
  UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
  // Set tag for under age of consent. NO means users are not under age
  // of consent.
  parameters.tagForUnderAgeOfConsent = NO;

  // Request an update for the consent information.
  [UMPConsentInformation.sharedInstance
      requestConsentInfoUpdateWithParameters:parameters
          completionHandler:^(NSError *_Nullable requestConsentError) {
            if (requestConsentError) {
              // Consent gathering failed.
              NSLog(@"Error: %@", requestConsentError.localizedDescription);
              return;
            }

            // TODO: Load and present the consent form.
          }];
}

צריך לטעון ולהציג טופס הסכמה, אם צריך

חשוב: ממשקי ה-API הבאים תואמים ל-UMP SDK בגרסה 2.1.0 ואילך.

לאחר קבלת סטטוס ההסכמה העדכני ביותר, אפשר להתקשר loadAndPresentIfRequiredFromViewController:completionHandler: לכיתהUMPConsentForm כדי לטעון טופס הסכמה. אם נדרש סטטוס הסכמה, ה-SDK יטען טופס ומיד יציג אותו מתוך view controller. completion handler נקרא אחרי סגירת הטופס. אם לא נדרשת הסכמה, completion handler הקריאה לקריאה מיידית.

Swift

override func viewDidLoad() {
  super.viewDidLoad()

  // Create a UMPRequestParameters object.
  let parameters = UMPRequestParameters()
  // Set tag for under age of consent. false means users are not under age
  // of consent.
  parameters.tagForUnderAgeOfConsent = false

  // Request an update for the consent information.
  UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: parameters) {
    [weak self] requestConsentError in
    guard let self else { return }

    if let consentError = requestConsentError {
      // Consent gathering failed.
      return print("Error: \(consentError.localizedDescription)")
    }

    UMPConsentForm.loadAndPresentIfRequired(from: self) {
      [weak self] loadAndPresentError in
      guard let self else { return }

      if let consentError = loadAndPresentError {
        // Consent gathering failed.
        return print("Error: \(consentError.localizedDescription)")
      }

      // Consent has been gathered.
    }
  }
}

Objective-C

- (void)viewDidLoad {
  [super viewDidLoad];

  // Create a UMPRequestParameters object.
  UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
  // Set tag for under age of consent. NO means users are not under age
  // of consent.
  parameters.tagForUnderAgeOfConsent = NO;

  __weak __typeof__(self) weakSelf = self;
  // Request an update for the consent information.
  [UMPConsentInformation.sharedInstance
      requestConsentInfoUpdateWithParameters:parameters
          completionHandler:^(NSError *_Nullable requestConsentError) {
            if (requestConsentError) {
              // Consent gathering failed.
              NSLog(@"Error: %@", requestConsentError.localizedDescription);
              return;
            }

            __strong __typeof__(self) strongSelf = weakSelf;
            if (!strongSelf) {
              return;
            }

            [UMPConsentForm loadAndPresentIfRequiredFromViewController:strongSelf
                completionHandler:^(NSError *loadAndPresentError) {
                  if (loadAndPresentError) {
                    // Consent gathering failed.
                    NSLog(@"Error: %@", loadAndPresentError.localizedDescription);
                    return;
                  }

                  // Consent has been gathered.
                }];
          }];
}

אם אתם צריכים לבצע פעולות כלשהן אחרי שהמשתמש בחר בטופס או סגר את הטופס, כדאי להציב את הלוגיקה הזו ב completion handlerבטופס.

בקשה להצגת מודעות

לפני שמבקשים להציג מודעות באפליקציה, צריך לבדוק אם קיבלתם הסכמה מהמשתמש באמצעות UMPConsentInformation.sharedInstance.canRequestAds. יש שני מקומות שבהם אפשר לבדוק את המידע בזמן קבלת ההסכמה:

  1. אחרי שמקבלים את בקשת ההסכמה בסשן הנוכחי.
  2. מיד לאחר שהתקשרת אל requestConsentInfoUpdateWithParameters:completionHandler:. יכול להיות שהבעת הסכמה כבר בסשן הקודם. כדי לקצר את זמן האחזור, מומלץ לא לחכות עד שהשיחה החוזרת תסתיים, כדי שתוכלו להתחיל לטעון את המודעות כמה שיותר מהר אחרי פתיחת האפליקציה.

גם אם תתרחש שגיאה בתהליך איסוף ההסכמה, עדיין כדאי לנסות לבקש מודעות. ה-UMP SDK משתמש בסטטוס ההסכמה מהסשן הקודם.

Swift

class ViewController: UIViewController {

  // Use a boolean to initialize the Google Mobile Ads SDK and load ads once.
  private var isMobileAdsStartCalled = false

  override func viewDidLoad() {
    super.viewDidLoad()

    // Create a UMPRequestParameters object.
    let parameters = UMPRequestParameters()
    // Set tag for under age of consent. false means users are not under age
    // of consent.
    parameters.tagForUnderAgeOfConsent = false

    // Request an update for the consent information.
    UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: parameters) {
      [weak self] requestConsentError in
      guard let self else { return }

      if let consentError = requestConsentError {
        // Consent gathering failed.
        return print("Error: \(consentError.localizedDescription)")
      }

      UMPConsentForm.loadAndPresentIfRequired(from: self) {
        [weak self] loadAndPresentError in
        guard let self else { return }

        if let consentError = loadAndPresentError {
          // Consent gathering failed.
          return print("Error: \(consentError.localizedDescription)")
        }

        // Consent has been gathered.
        if UMPConsentInformation.sharedInstance.canRequestAds {
          self.startGoogleMobileAdsSDK()
        }
      }
    }
    
    // Check if you can initialize the Google Mobile Ads SDK in parallel
    // while checking for new consent information. Consent obtained in
    // the previous session can be used to request ads.
    if UMPConsentInformation.sharedInstance.canRequestAds {
      startGoogleMobileAdsSDK()
    }
  }
  
  private func startGoogleMobileAdsSDK() {
    DispatchQueue.main.async {
      guard !self.isMobileAdsStartCalled else { return }

      self.isMobileAdsStartCalled = true

      // Initialize the Google Mobile Ads SDK.
      GADMobileAds.sharedInstance().start()

      // TODO: Request an ad.
      // GADInterstitialAd.load(...)
    }
  }
}

Objective-C

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];

  // Create a UMPRequestParameters object.
  UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
  // Set tag for under age of consent. NO means users are not under age
  // of consent.
  parameters.tagForUnderAgeOfConsent = NO;

  __weak __typeof__(self) weakSelf = self;
  // Request an update for the consent information.
  [UMPConsentInformation.sharedInstance
      requestConsentInfoUpdateWithParameters:parameters
          completionHandler:^(NSError *_Nullable requestConsentError) {
            if (requestConsentError) {
              // Consent gathering failed.
              NSLog(@"Error: %@", requestConsentError.localizedDescription);
              return;
            }
            __strong __typeof__(self) strongSelf = weakSelf;
            if (!strongSelf) {
              return;
            }

            [UMPConsentForm loadAndPresentIfRequiredFromViewController:strongSelf
                completionHandler:^(NSError *loadAndPresentError) {
                  if (loadAndPresentError) {
                    // Consent gathering failed.
                    NSLog(@"Error: %@", loadAndPresentError.localizedDescription);
                    return;
                  }

                  // Consent has been gathered.
                  __strong __typeof__(self) strongSelf = weakSelf;
                  if (!strongSelf) {
                    return;
                  }

                  if (UMPConsentInformation.sharedInstance.canRequestAds) {
                    [strongSelf startGoogleMobileAdsSDK];
                  }
                }];
          }];

  // Check if you can initialize the Google Mobile Ads SDK in parallel
  // while checking for new consent information. Consent obtained in
  // the previous session can be used to request ads.
  if (UMPConsentInformation.sharedInstance.canRequestAds) {
    [self startGoogleMobileAdsSDK];
  }
}

- (void)startGoogleMobileAdsSDK {
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    // Initialize the Google Mobile Ads SDK.
    [GADMobileAds.sharedInstance startWithCompletionHandler:nil];

    // TODO: Request an ad.
    // [GADInterstitialAd loadWithAdUnitID...];
  });
}

אפשרויות פרטיות

טופסי הסכמה מסוימים מחייבים את המשתמש לשנות את הסכמתו בכל שלב. אם צריך, פועלים לפי השלבים הבאים כדי להטמיע לחצן של אפשרויות פרטיות.

לשם כך:

  1. אתם צריכים להטמיע רכיב בממשק המשתמש, כמו לחצן בדף ההגדרות של האפליקציה, שיכול להפעיל טופס בנושא אפשרויות פרטיות.
  2. אחרי סיום loadAndPresentIfRequiredFromViewController:completionHandler: , צריך לבדוק את privacyOptionsRequirementStatus כדי לקבוע אם להציג את הרכיב של ממשק המשתמש שיכול להציג את טופס אפשרויות הפרטיות.
  3. כשמשתמש יוצר אינטראקציה עם הרכיב בממשק המשתמש, צריך לבצע קריאה ל-presentPrivacyOptionsFormFromViewController:completionHandler: כדי להציג את הטופס, כדי שהוא יוכל לעדכן את אפשרויות הפרטיות בכל שלב.

הדוגמה הבאה ממחישה איך להציג את טופס אפשרויות הפרטיות מתוך UIBarButtonItem.

Swift

@IBOutlet weak var privacySettingsButton: UIBarButtonItem!

var isPrivacyOptionsRequired: Bool {
  return UMPConsentInformation.shared.privacyOptionsRequirementStatus == .required
}

override func viewDidLoad() {
  // ...

  // Request an update for the consent information.
  UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(with: parameters) {
    // ...

    UMPConsentForm.loadAndPresentIfRequired(from: self) {
      //...

      // Consent has been gathered.

      // Show the button if privacy options are required.
      self.privacySettingsButton.isEnabled = isPrivacyOptionsRequired
    }
  }
  // ...
}

// Present the privacy options form when a user interacts with the
// privacy settings button.
@IBAction func privacySettingsTapped(_ sender: UIBarButtonItem) {
  UMPConsentForm.presentPrivacyOptionsForm(from: self) {
    [weak self] formError in
    guard let self, let formError else { return }

    // Handle the error.
  }
}

Objective-C

@interface ViewController ()
@property(weak, nonatomic) IBOutlet UIBarButtonItem *privacySettingsButton;
@end

- (BOOL)isPrivacyOptionsRequired {
  return UMPConsentInformation.sharedInstance.privacyOptionsRequirementStatus ==
         UMPPrivacyOptionsRequirementStatusRequired;
}

- (void)viewDidLoad {
  // ...

  __weak __typeof__(self) weakSelf = self;
  // Request an update for the consent information.
  [UMPConsentInformation.sharedInstance
      requestConsentInfoUpdateWithParameters:parameters
          completionHandler:^(NSError *_Nullable requestConsentError) {
            // ...

            [UMPConsentForm loadAndPresentIfRequiredFromViewController:strongSelf
                completionHandler:^(NSError *loadAndPresentError) {
                  // ...

                  // Consent has been gathered.

                  // Show the button if privacy options are required.
                  strongSelf.privacySettingsButton.enabled = isPrivacyOptionsRequired;
                }];
          }];
}

// Present the privacy options form when a user interacts with your
// privacy settings button.
- (IBAction)privacySettingsTapped:(UIBarButtonItem *)sender {
  [UMPConsentForm presentPrivacyOptionsFormFromViewController:self
                                completionHandler:^(NSError *_Nullable formError) {
                                  if (formError) {
                                    // Handle the error.
                                  }
                                }];
}

בדיקה

אם אתם רוצים לבדוק את השילוב באפליקציה במהלך הפיתוח, פעלו לפי השלבים הבאים כדי לרשום את מכשיר הבדיקה באופן פרוגרמטי.

  1. התקשרות אל requestConsentInfoUpdateWithParameters:completionHandler:.
  2. חפשו בפלט היומן הודעה שנראית כמו ההודעה שלמטה, שבה מוצג מזהה המכשיר שלכם ואיך מוסיפים אותו כמכשיר בדיקה:

    <UMP SDK>To enable debug mode for this device, set: UMPDebugSettings.testDeviceIdentifiers = @[2077ef9a63d2b398840261c8221a0c9b]
    
  3. מעתיקים את מזהה מכשיר הבדיקה ללוח.

  4. משנים את הקוד כדי להתקשר UMPDebugSettings().testDeviceIdentifiers ומעבירים לרשימה של מזהי מכשירי הבדיקה.

Swift

let parameters = UMPRequestParameters()
let debugSettings = UMPDebugSettings()
debugSettings.testDeviceIdentifiers = ["TEST-DEVICE-HASHED-ID"]
parameters.debugSettings = debugSettings
// Include the UMPRequestParameters in your consent request.
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(
    with: parameters,
    completionHandler: { error in
      ...
    })

Objective-C

UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
UMPDebugSettings *debugSettings = [[UMPDebugSettings alloc] init];
debugSettings.testDeviceIdentifiers = @[ @"TEST-DEVICE-HASHED-ID" ];
parameters.debugSettings = debugSettings;
// Include the UMPRequestParameters in your consent request.
[UMPConsentInformation.sharedInstance
    requestConsentInfoUpdateWithParameters:parameters
                        completionHandler:^(NSError *_Nullable error){
                          ...
}];

אילוץ מיקום גיאוגרפי

ה-UMP SDK מאפשר לבדוק את התנהגות האפליקציה כאילו המכשיר נמצא באזור הכלכלי האירופי או בבריטניה באמצעות the debugGeography property of type UMPDebugGeography on UMPDebugSettings. שימו לב שהגדרות ניפוי הבאגים פועלות רק במכשירי בדיקה.

Swift

let parameters = UMPRequestParameters()
let debugSettings = UMPDebugSettings()
debugSettings.testDeviceIdentifiers = ["TEST-DEVICE-HASHED-ID"]
debugSettings.geography = .EEA
parameters.debugSettings = debugSettings
// Include the UMPRequestParameters in your consent request.
UMPConsentInformation.sharedInstance.requestConsentInfoUpdate(
    with: parameters,
    completionHandler: { error in
      ...
    })

Objective-C

UMPRequestParameters *parameters = [[UMPRequestParameters alloc] init];
UMPDebugSettings *debugSettings = [[UMPDebugSettings alloc] init];
debugSettings.testDeviceIdentifiers = @[ @"TEST-DEVICE-HASHED-ID" ];
debugSettings.geography = UMPDebugGeographyEEA;
parameters.debugSettings = debugSettings;
// Include the UMPRequestParameters in your consent request.
[UMPConsentInformation.sharedInstance
    requestConsentInfoUpdateWithParameters:parameters
                         completionHandler:^(NSError *_Nullable error){
                           ...
}];

בבדיקת האפליקציה באמצעות UMP SDK, כדאי לאפס את מצב ה-SDK כדי לדמות את חוויית ההתקנה הראשונה של המשתמש. ה-SDK מספק את השיטה reset לעשות זאת.

Swift

UMPConsentInformation.sharedInstance.reset()

Objective-C

[UMPConsentInformation.sharedInstance reset];

דוגמאות ב-GitHub

דוגמאות לשילוב של UMP SDK: Swift | Objective-C