אירועים בהתאמה אישית של מודעות מותאמות

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

משלימים את הגדרת האירועים המותאמים אישית.

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

כשמגיעים לפריט המותאם אישית של האירוע בשרשרת תהליך בחירת הרשת (Mediation) ב-Waterfall, מתבצעת קריאה ל-method‏ loadNativeAd:adConfiguration:completionHandler: בשם המחלקה שציינתם כשיצרתם אירוע מותאם אישית. במקרה הזה, ה-method נמצא ב-SampleCustomEvent, שקורא ל-method‏ loadNativeAd:adConfiguration:completionHandler: ב-SampleCustomEventNative.

כדי לבקש מודעה מותאמת, צריך ליצור או לשנות מחלקה שמטמיעה את GADMediationAdapter ואת loadNativeAd:adConfiguration:completionHandler:. אם כבר קיימת מחלקה שמרחיבה את GADMediationAdapter, צריך להטמיע את loadNativeAd:adConfiguration:completionHandler: שם. בנוסף, יוצרים כיתה חדשה כדי להטמיע את GADMediationNativeAd.

בדוגמה של האירוע המותאם אישית, SampleCustomEvent מטמיע את הממשק GADMediationAdapter ואז מעביר את ההרשאה ל-SampleCustomEventNative.

Swift

import GoogleMobileAds

class SampleCustomEvent: NSObject, MediationAdapter {

  fileprivate var nativeAd: SampleCustomEventNativeAd?

  func loadNativeAd(
    for adConfiguration: MediationNativeAdConfiguration,
    completionHandler: @escaping GADMediationNativeAdLoadCompletionHandler
  ) {
    self.nativeAd = SampleCustomEventNativeAd()
    self.nativeAd?.loadNativeAd(
      for: adConfiguration, completionHandler: completionHandler)
  }
}

Objective-C

#import "SampleCustomEvent.h"

@implementation SampleCustomEvent

SampleCustomEventNativeAd *sampleNativeAd;

- (void)loadNativeAdForAdConfiguration:
            (GADMediationNativeAdConfiguration *)adConfiguration
                     completionHandler:
                         (GADMediationNativeAdLoadCompletionHandler)
                             completionHandler {
  sampleNative = [[SampleCustomEventNativeAd alloc] init];
  [sampleNative loadNativeAdForAdConfiguration:adConfiguration
                             completionHandler:completionHandler];
}

הקובץ SampleCustomEventNative` אחראי למשימות הבאות:

  • טעינת המודעה המותאמת

  • הטמעה של פרוטוקול GADMediationNativeAd.

  • קבלת נתונים של קריאות חוזרות (callback) של אירועים שקשורים למודעות ודיווח עליהם אל Google Mobile Ads SDK.

הפרמטר האופציונלי שהוגדר בממשק המשתמש של Ad Manager נכלל בהגדרת המודעה. אפשר לגשת לפרמטר דרך adConfiguration.credentials.settings[@"parameter"]. הפרמטר הזה הוא בדרך כלל מזהה של יחידת מודעות שנדרש על ידי SDK של רשת מודעות כשיוצרים מופע של אובייקט מודעה.

Swift

class SampleCustomEventNativeAd: NSObject, MediationNativeAd {
  /// The Sample Ad Network native ad.
  var nativeAd: SampleNativeAd?

  /// The ad event delegate to forward ad rendering events to the Google Mobile
  /// Ads SDK.
  var delegate: MediationNativeAdEventDelegate?

  /// Completion handler called after ad load
  var completionHandler: GADMediationNativeLoadCompletionHandler?

  func loadNativeAd(
    for adConfiguration: MediationNativeAdConfiguration,
    completionHandler: @escaping GADMediationNativeLoadCompletionHandler
  ) {
    let adLoader = SampleNativeAdLoader()
    let sampleRequest = SampleNativeAdRequest()

    // Google Mobile Ads SDK requires the image assets to be downloaded
    // automatically unless the publisher specifies otherwise by using the
    // GADNativeAdImageAdLoaderOptions object's disableImageLoading property. If
    // your network doesn't have an option like this and instead only ever
    // returns URLs for images (rather than the images themselves), your adapter
    // should download image assets on behalf of the publisher. This should be
    // done after receiving the native ad object from your network's SDK, and
    // before calling the connector's adapter:didReceiveMediatedNativeAd: method.
    sampleRequest.shouldDownloadImages = true
    sampleRequest.preferredImageOrientation = NativeAdImageOrientation.any
    sampleRequest.shouldRequestMultipleImages = false
    let options = adConfiguration.options
    for loaderOptions: AdLoaderOptions in options {
      if let imageOptions = loaderOptions as? NativeAdImageAdLoaderOptions {
        sampleRequest.shouldRequestMultipleImages =
          imageOptions.shouldRequestMultipleImages
        // If the GADNativeAdImageAdLoaderOptions' disableImageLoading property is
        // YES, the adapter should send just the URLs for the images.
        sampleRequest.shouldDownloadImages = !imageOptions.disableImageLoading
      } else if let mediaOptions = loaderOptions
        as? NativeAdMediaAdLoaderOptions
      {
        switch mediaOptions.mediaAspectRatio {
        case MediaAspectRatio.landscape:
          sampleRequest.preferredImageOrientation =
            NativeAdImageOrientation.landscape
        case MediaAspectRatio.portrait:
          sampleRequest.preferredImageOrientation =
            NativeAdImageOrientation.portrait
        default:
          sampleRequest.preferredImageOrientation = NativeAdImageOrientation.any
        }
      }
    }
    // This custom event uses the server parameter to carry an ad unit ID, which
    // is the most common use case.
    adLoader.delegate = self
    adLoader.adUnitID =
      adConfiguration.credentials.settings["parameter"] as? String
    self.completionHandler = completionHandler
    adLoader.fetchAd(sampleRequest)
  }
}

Objective-C

#import "SampleCustomEventNativeAd.h"

@interface SampleCustomEventNativeAd () <SampleNativeAdDelegate,
                                         GADMediationNativeAd> {
  /// The sample native ad.
  SampleNativeAd *_nativeAd;

  /// The completion handler to call when the ad loading succeeds or fails.
  GADMediationNativeLoadCompletionHandler _loadCompletionHandler;

  /// The ad event delegate to forward ad rendering events to the Google Mobile
  /// Ads SDK.
  id<GADMediationNativeAdEventDelegate> _adEventDelegate;
}
@end

- (void)loadNativeAdForAdConfiguration:
            (GADMediationNativeAdConfiguration *)adConfiguration
                     completionHandler:(GADMediationNativeLoadCompletionHandler)
                                           completionHandler {
  __block atomic_flag completionHandlerCalled = ATOMIC_FLAG_INIT;
  __block GADMediationNativeLoadCompletionHandler originalCompletionHandler =
      [completionHandler copy];

  _loadCompletionHandler = ^id<GADMediationNativeAdEventDelegate>(
      _Nullable id<GADMediationNativeAd> ad, NSError *_Nullable error) {
    // Only allow completion handler to be called once.
    if (atomic_flag_test_and_set(&completionHandlerCalled)) {
      return nil;
    }

    id<GADMediationNativeAdEventDelegate> delegate = nil;
    if (originalCompletionHandler) {
      // Call original handler and hold on to its return value.
      delegate = originalCompletionHandler(ad, error);
    }

    // Release reference to handler. Objects retained by the handler will also
    // be released.
    originalCompletionHandler = nil;

    return delegate;
  };

  SampleNativeAdLoader *adLoader = [[SampleNativeAdLoader alloc] init];
  SampleNativeAdRequest *sampleRequest = [[SampleNativeAdRequest alloc] init];

  // Google Mobile Ads SDK requires the image assets to be downloaded
  // automatically unless the publisher specifies otherwise by using the
  // GADNativeAdImageAdLoaderOptions object's disableImageLoading property. If
  // your network doesn't have an option like this and instead only ever returns
  // URLs for images (rather than the images themselves), your adapter should
  // download image assets on behalf of the publisher. This should be done after
  // receiving the native ad object from your network's SDK, and before calling
  // the connector's adapter:didReceiveMediatedNativeAd: method.
  sampleRequest.shouldDownloadImages = YES;

  sampleRequest.preferredImageOrientation = NativeAdImageOrientationAny;
  sampleRequest.shouldRequestMultipleImages = NO;
  sampleRequest.testMode = adConfiguration.isTestRequest;

  for (GADAdLoaderOptions *loaderOptions in adConfiguration.options) {
    if ([loaderOptions isKindOfClass:[GADNativeAdImageAdLoaderOptions class]]) {
      GADNativeAdImageAdLoaderOptions *imageOptions =
          (GADNativeAdImageAdLoaderOptions *)loaderOptions;
      sampleRequest.shouldRequestMultipleImages =
          imageOptions.shouldRequestMultipleImages;

      // If the GADNativeAdImageAdLoaderOptions' disableImageLoading property is
      // YES, the adapter should send just the URLs for the images.
      sampleRequest.shouldDownloadImages = !imageOptions.disableImageLoading;
    } else if ([loaderOptions
                   isKindOfClass:[GADNativeAdMediaAdLoaderOptions class]]) {
      GADNativeAdMediaAdLoaderOptions *mediaOptions =
          (GADNativeAdMediaAdLoaderOptions *)loaderOptions;
      switch (mediaOptions.mediaAspectRatio) {
        case GADMediaAspectRatioLandscape:
          sampleRequest.preferredImageOrientation =
              NativeAdImageOrientationLandscape;
          break;
        case GADMediaAspectRatioPortrait:
          sampleRequest.preferredImageOrientation =
              NativeAdImageOrientationPortrait;
          break;
        default:
          sampleRequest.preferredImageOrientation = NativeAdImageOrientationAny;
          break;
      }
    } else if ([loaderOptions isKindOfClass:[GADNativeAdViewAdOptions class]]) {
      _nativeAdViewAdOptions = (GADNativeAdViewAdOptions *)loaderOptions;
    }
  }

  // This custom event uses the server parameter to carry an ad unit ID, which
  // is the most common use case.
  NSString *adUnit = adConfiguration.credentials.settings[@"parameter"];
  adLoader.adUnitID = adUnit;
  adLoader.delegate = self;

  [adLoader fetchAd:sampleRequest];
}

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

בדרך כלל, השיטות האלה מוטמעות בתוך קריאות חוזרות (callbacks) מ-SDK של צד שלישי שהמתאם מטמיע. בדוגמה הזו, ל-Sample SDK יש SampleNativeAdDelegate עם קריאות חוזרות רלוונטיות:

Swift

func adLoader(
  _ adLoader: SampleNativeAdLoader, didReceive nativeAd: SampleNativeAd
) {
  extraAssets = [
    SampleCustomEventConstantsSwift.awesomenessKey: nativeAd.degreeOfAwesomeness
      ?? ""
  ]

  if let image = nativeAd.image {
    images = [NativeAdImage(image: image)]
  } else {
    let imageUrl = URL(fileURLWithPath: nativeAd.imageURL)
    images = [NativeAdImage(url: imageUrl, scale: nativeAd.imageScale)]
  }
  if let mappedIcon = nativeAd.icon {
    icon = NativeAdImage(image: mappedIcon)
  } else {
    let iconURL = URL(fileURLWithPath: nativeAd.iconURL)
    icon = NativeAdImage(url: iconURL, scale: nativeAd.iconScale)
  }

  adChoicesView = SampleAdInfoView()
  self.nativeAd = nativeAd
  if let handler = completionHandler {
    delegate = handler(self, nil)
  }
}

func adLoader(
  _ adLoader: SampleNativeAdLoader,
  didFailToLoadAdWith errorCode: SampleErrorCode
) {
  let error =
    SampleCustomEventUtilsSwift.SampleCustomEventErrorWithCodeAndDescription(
      code: SampleCustomEventErrorCodeSwift
        .SampleCustomEventErrorAdLoadFailureCallback,
      description:
        "Sample SDK returned an ad load failure callback with error code: \(errorCode)"
    )
  if let handler = completionHandler {
    delegate = handler(nil, error)
  }
}

Objective-C

- (void)adLoader:(SampleNativeAdLoader *)adLoader
    didReceiveNativeAd:(SampleNativeAd *)nativeAd {
  if (nativeAd.image) {
    _images = @[ [[GADNativeAdImage alloc] initWithImage:nativeAd.image] ];
  } else {
    NSURL *imageURL = [[NSURL alloc] initFileURLWithPath:nativeAd.imageURL];
    _images = @[ [[GADNativeAdImage alloc] initWithURL:imageURL
                                                 scale:nativeAd.imageScale] ];
  }

  if (nativeAd.icon) {
    _icon = [[GADNativeAdImage alloc] initWithImage:nativeAd.icon];
  } else {
    NSURL *iconURL = [[NSURL alloc] initFileURLWithPath:nativeAd.iconURL];
    _icon = [[GADNativeAdImage alloc] initWithURL:iconURL
                                            scale:nativeAd.iconScale];
  }

  // The sample SDK provides an AdChoices view (SampleAdInfoView). If your SDK
  // provides image and click through URLs for its AdChoices icon instead of an
  // actual UIView, the adapter is responsible for downloading the icon image
  // and creating the AdChoices icon view.
  _adChoicesView = [[SampleAdInfoView alloc] init];
  _nativeAd = nativeAd;

  _adEventDelegate = _loadCompletionHandler(self, nil);
}

- (void)adLoader:(SampleNativeAdLoader *)adLoader
    didFailToLoadAdWithErrorCode:(SampleErrorCode)errorCode {
  NSError *error = SampleCustomEventErrorWithCodeAndDescription(
      SampleCustomEventErrorAdLoadFailureCallback,
      [NSString stringWithFormat:@"Sample SDK returned an ad load failure "
                                 @"callback with error code: %@",
                                 errorCode]);
  _adEventDelegate = _loadCompletionHandler(nil, error);
}

מודעות מותאמות במפות

לכל SDK יש פורמטים ייחודיים משלו למודעות מותאמות. לדוגמה, יכול להיות שפונקציה אחת תחזיר אובייקטים שמכילים שדה בשם title, ואילו פונקציה אחרת תחזיר אובייקטים עם שדה בשם headline. בנוסף, השיטות שמשמשות למעקב אחר חשיפות ולעיבוד קליקים יכולות להיות שונות מ-SDK אחד לאחר.

כדי לפתור את הבעיות האלה, כשאירוע מותאם אישית מקבל אובייקט של מודעה מותאמת מ-SDK של רשת מתווכת, הוא צריך להשתמש במחלקה שמטמיעה את GADMediationNativeAd, כמו SampleCustomEventNativeAd, כדי לבצע מיפוי של אובייקט המודעה המותאמת של ה-SDK המתווך כך שיתאים לממשק שנדרש על ידי Google Mobile Ads SDK.

עכשיו נתעמק בפרטי ההטמעה של SampleCustomEventNativeAd.

אחסון המיפויים

מצפים מ-GADMediationNativeAd להטמיע מאפיינים מסוימים שממופים ממאפיינים של ערכות SDK אחרות:

Swift

var nativeAd: SampleNativeAd?

var headline: String? {
  return nativeAd?.headline
}

var images: [NativeAdImage]?

var body: String? {
  return nativeAd?.body
}

var icon: NativeAdImage?

var callToAction: String? {
  return nativeAd?.callToAction
}

var starRating: NSDecimalNumber? {
  return nativeAd?.starRating
}

var store: String? {
  return nativeAd?.store
}

var price: String? {
  return nativeAd?.price
}

var advertiser: String? {
  return nativeAd?.advertiser
}

var extraAssets: [String: Any]? {
  return [
    SampleCustomEventConstantsSwift.awesomenessKey:
      nativeAd?.degreeOfAwesomeness
      ?? ""
  ]
}

var adChoicesView: UIView?

var mediaView: UIView? {
  return nativeAd?.mediaView
}

Objective-C

/// Used to store the ad's images. In order to implement the
/// GADMediationNativeAd protocol, we use this class to return the images
/// property.
NSArray<GADNativeAdImage *> *_images;

/// Used to store the ad's icon. In order to implement the GADMediationNativeAd
/// protocol, we use this class to return the icon property.
GADNativeAdImage *_icon;

/// Used to store the ad's ad choices view. In order to implement the
/// GADMediationNativeAd protocol, we use this class to return the adChoicesView
/// property.
UIView *_adChoicesView;

- (nullable NSString *)headline {
  return _nativeAd.headline;
}

- (nullable NSArray<GADNativeAdImage *> *)images {
  return _images;
}

- (nullable NSString *)body {
  return _nativeAd.body;
}

- (nullable GADNativeAdImage *)icon {
  return _icon;
}

- (nullable NSString *)callToAction {
  return _nativeAd.callToAction;
}

- (nullable NSDecimalNumber *)starRating {
  return _nativeAd.starRating;
}

- (nullable NSString *)store {
  return _nativeAd.store;
}

- (nullable NSString *)price {
  return _nativeAd.price;
}

- (nullable NSString *)advertiser {
  return _nativeAd.advertiser;
}

- (nullable NSDictionary<NSString *, id> *)extraAssets {
  return
      @{SampleCustomEventExtraKeyAwesomeness : _nativeAd.degreeOfAwesomeness};
}

- (nullable UIView *)adChoicesView {
  return _adChoicesView;
}

- (nullable UIView *)mediaView {
  return _nativeAd.mediaView;
}

- (BOOL)hasVideoContent {
  return self.mediaView != nil;
}

רשתות מסוימות שמופעל בהן תהליך בחירת הרשת באופן אוטומטי יכולות לספק נכסים נוספים מעבר לאלה שמוגדרים על ידי Google Mobile Ads SDK. פרוטוקול GADMediationNativeAd כולל שיטה בשם extraAssets ש-Google Mobile Ads SDK משתמש בה כדי לאחזר נכסים 'נוספים' מהמיפוי שלכם.

נכסי תמונות של מפות

מיפוי של נכסי תמונות הוא תהליך מורכב יותר ממיפוי של סוגי נתונים פשוטים יותר כמו NSString או double. יכול להיות שהתמונות יורדו באופן אוטומטי או שיוחזרו כערכי כתובות URL. גם צפיפות הפיקסלים יכולה להיות שונה.

כדי לעזור לכם לנהל את הפרטים האלה, Google Mobile Ads SDK מספק את המחלקה GADNativeAdImage. צריך להחזיר את פרטי נכס התמונה (אם מדובר באובייקטים בפועל UIImage או רק בערכים NSURL) אל Google Mobile Ads SDK באמצעות המחלקה הזו.

כך מחלקת המיפוי מטפלת ביצירת GADNativeAdImage כדי להכיל את תמונת הסמל:

Swift

if let image = nativeAd.image {
  images = [NativeAdImage(image: image)]
} else {
  let imageUrl = URL(fileURLWithPath: nativeAd.imageURL)
  images = [NativeAdImage(url: imageUrl, scale: nativeAd.imageScale)]
}

Objective-C

if (nativeAd.image) {
  _images = @[ [[GADNativeAdImage alloc] initWithImage:nativeAd.image] ];
} else {
  NSURL *imageURL = [[NSURL alloc] initFileURLWithPath:nativeAd.imageURL];
  _images = @[ [[GADNativeAdImage alloc] initWithURL:imageURL
                                               scale:nativeAd.imageScale] ];
}

אירועי חשיפה וקליק

גם Google Mobile Ads SDK וגם ה-SDK של הרשת המתווכת צריכים לדעת מתי מתרחשת חשיפה או מתי מתרחש קליק, אבל רק אחד מהם צריך לעקוב אחרי האירועים האלה. יש שני סוגים של אירועים מותאמים אישית, בהתאם לשאלה אם ה-SDK של הרשת המגשרת תומך במעקב אחרי חשיפות וקליקים באופן עצמאי.

מעקב אחרי קליקים וחשיפות באמצעות Google Mobile Ads SDK

אם ה-SDK של הרשת המתווכת לא מבצע מעקב משלו אחר חשיפות וקליקים, אבל מספק שיטות לתיעוד קליקים וחשיפות, Google Mobile Ads SDK יכול לעקוב אחרי האירועים האלה ולעדכן את המתאם. פרוטוקול GADMediationNativeAd כולל שתי שיטות: didRecordImpression: ו-didRecordClickOnAssetWithName:view:viewController:. אירועים בהתאמה אישית יכולים להטמיע את השיטות האלה כדי להפעיל את השיטה המתאימה באובייקט של המודעה המקורית שמוצגת באמצעות גישור:

Swift

func didRecordImpression() {
  nativeAd?.recordImpression()
}

func didRecordClickOnAsset(
  withName assetName: GADUnifiedNativeAssetIdentifier,
  view: UIView,
  wController: UIViewController
) {
  nativeAd?.handleClick(on: view)
}

Objective-C

- (void)didRecordImpression {
  if (self.nativeAd) {
    [self.nativeAd recordImpression];
  }
}

- (void)didRecordClickOnAssetWithName:(GADUnifiedNativeAssetIdentifier)assetName
                                 view:(UIView *)view
                       viewController:(UIViewController *)viewController {
  if (self.nativeAd) {
    [self.nativeAd handleClickOnView:view];
  }
}

מכיוון שהמחלקה שמטמיעה את פרוטוקול GADMediationNativeAd מחזיקה הפניה לאובייקט המודעה המקורית של ה-SDK לדוגמה, היא יכולה לקרוא לשיטה המתאימה באובייקט הזה כדי לדווח על קליק או חשיפה. שימו לב שהשיטה didRecordClickOnAssetWithName:view:viewController: מקבלת פרמטר אחד: אובייקט View שמתאים לנכס של המודעה המקורית שקיבל את הקליק.

מעקב אחר קליקים וחשיפות באמצעות ה-SDK של הגישור

יכול להיות שחלק מה-SDKs של רשתות בתיווך יעדיפו לעקוב אחרי קליקים וחשיפות בעצמם. במקרה כזה, צריך להטמיע את השיטות handlesUserClicks ו-handlesUserImpressions כמו שמוצג בקטע הקוד שלמטה. כשמחזירים YES, מציינים שהאירוע המותאם אישית אחראי למעקב אחרי האירועים האלה, ויודיע ל-Google Mobile Ads SDK כשהאירועים האלה יתרחשו.

אירועים מותאמים אישית שמבטלים את המעקב אחרי קליקים וחשיפות יכולים להשתמש בהודעה didRenderInView: כדי להעביר את התצוגה של המודעה המותאמת לאובייקט המודעה המותאמת של ה-SDK המגשר, וכך לאפשר ל-SDK המגשר לבצע את המעקב בפועל. ה-SDK לדוגמה מתוך פרויקט הדוגמה של האירוע המותאם אישית שלנו (שממנו נלקחו קטעי הקוד במדריך הזה) לא משתמש בגישה הזו, אבל אם הוא היה משתמש בה, קוד האירוע המותאם אישית היה קורא לשיטה setNativeAdView:view: כמו שמוצג בקטע הקוד הבא:

Swift

func handlesUserClicks() -> Bool {
  return true
}
func handlesUserImpressions() -> Bool {
  return true
}

func didRender(
  in view: UIView, clickableAssetViews: [GADNativeAssetIdentifier: UIView],
  nonclickableAssetViews: [GADNativeAssetIdentifier: UIView],
  viewController: UIViewController
) {
  // This method is called when the native ad view is rendered. Here you would pass the UIView
  // back to the mediated network's SDK.
  self.nativeAd?.setNativeAdView(view)
}

Objective-C

- (BOOL)handlesUserClicks {
  return YES;
}

- (BOOL)handlesUserImpressions {
  return YES;
}

- (void)didRenderInView:(UIView *)view
       clickableAssetViews:(NSDictionary<GADNativeAssetIdentifier, UIView *> *)
                               clickableAssetViews
    nonclickableAssetViews:(NSDictionary<GADNativeAssetIdentifier, UIView *> *)
                               nonclickableAssetViews
            viewController:(UIViewController *)viewController {
  // This method is called when the native ad view is rendered. Here you would
  // pass the UIView back to the mediated network's SDK. Playing video using
  // SampleNativeAd's playVideo method
  [_nativeAd setNativeAdView:view];
}

העברת אירועי תהליך בחירת רשת מודעות אל Google Mobile Ads SDK

אחרי שמבצעים קריאה ל-GADMediationNativeLoadCompletionHandler עם מודעה שנטענה, אפשר להשתמש באובייקט GADMediationNativeAdEventDelegate delegate שהוחזר על ידי המתאם כדי להעביר אירועי הצגה מ-SDK של צד שלישי אל Google Mobile Ads SDK.

חשוב שהאירוע המותאם אישית יעביר כמה שיותר מהקריאות החוזרות האלה, כדי שהאפליקציה תקבל את האירועים המקבילים האלה מ-Google Mobile Ads SDK. דוגמה לשימוש בפונקציות קריאה חוזרת:

כך מסיימים את ההטמעה של אירועים מותאמים אישית במודעות מותאמות. הדוגמה המלאה זמינה ב-GitHub.