Предпосылки
Завершите настройку пользовательских событий .
Запросить нативную рекламу
При достижении элемента строки пользовательского события в каскадной цепочке медиации вызывается метод loadNativeAd:adConfiguration:completionHandler:
для имени класса, указанного вами при создании пользовательского события . В данном случае этот метод находится в SampleCustomEvent
, который затем вызывает метод loadNativeAd:adConfiguration:completionHandler:
в SampleCustomEventNative
.
Чтобы запросить нативную рекламу, создайте или измените класс, реализующий GADMediationAdapter
и loadNativeAd:adConfiguration:completionHandler:
. Если класс, расширяющий GADMediationAdapter
уже существует, реализуйте в нём loadNativeAd:adConfiguration:completionHandler:
. Кроме того, создайте новый класс для реализации GADMediationNativeAd
.
В нашем примере пользовательского события SampleCustomEvent
реализует интерфейс GADMediationAdapter
, а затем делегирует полномочия SampleCustomEventNative
.
Быстрый
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
.Получение и отправка обратных вызовов рекламных событий в Google Mobile Ads SDK
Необязательный параметр, определённый в пользовательском интерфейсе AdMob, включён в конфигурацию объявления. Доступ к нему можно получить через adConfiguration.credentials.settings[@"parameter"]
. Обычно этот параметр представляет собой идентификатор рекламного блока, который SDK рекламной сети требует при создании экземпляра объекта объявления.
Быстрый
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() // The 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]; // The 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
для параметра error; в случае неудачи передайте возникшую ошибку.
Обычно эти методы реализуются внутри обратных вызовов стороннего SDK, который реализует ваш адаптер. В данном примере в Sample SDK есть SampleNativeAdDelegate
с соответствующими обратными вызовами:
Быстрый
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:
Быстрый
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 с помощью этого класса.
Вот как класс mapper обрабатывает создание GADNativeAdImage
для хранения изображения значка:
Быстрый
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 должен отслеживать эти события. Существует два разных подхода к пользовательским событиям, в зависимости от того, поддерживает ли опосредованный SDK отслеживание показов и кликов самостоятельно.
Отслеживайте клики и показы с помощью Google Mobile Ads SDK
Если опосредованный SDK не отслеживает показы и клики самостоятельно, но предоставляет методы для регистрации кликов и показов, Google Mobile Ads SDK может отслеживать эти события и уведомлять адаптер. Протокол GADMediationNativeAd
включает два метода: didRecordImpression:
и didRecordClickOnAssetWithName:view:viewController:
которые пользовательские события могут реализовать для вызова соответствующего метода в объекте опосредованной нативной рекламы:
Быстрый
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
, содержит ссылку на объект нативной рекламы из Sample SDK, он может вызвать соответствующий метод этого объекта для сообщения о клике или показе. Обратите внимание, что метод didRecordClickOnAssetWithName:view:viewController:
принимает один параметр: объект View
, соответствующий активу нативной рекламы, по которому был совершен клик.
Отслеживайте клики и показы с помощью опосредованного SDK
Некоторые опосредованные SDK могут предпочесть самостоятельное отслеживание кликов и показов. В этом случае следует реализовать методы handlesUserClicks
и handlesUserImpressions
, как показано во фрагменте ниже. Возвращая значение YES
, вы указываете, что пользовательское событие берёт на себя ответственность за отслеживание этих событий и будет уведомлять Google Mobile Ads SDK об их возникновении.
Пользовательские события, переопределяющие отслеживание кликов и показов, могут использовать сообщение didRenderInView:
для передачи представления нативного объявления объекту нативного объявления опосредованного SDK, чтобы опосредованный SDK мог выполнить фактическое отслеживание. В примере SDK из нашего проекта с пользовательскими событиями (из которого взяты фрагменты кода для этого руководства) этот подход не используется, но если бы он использовался, код пользовательского события вызывал бы метод setNativeAdView:view:
как показано во фрагменте ниже:
Быстрый
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
может использоваться адаптером для пересылки событий презентации из стороннего SDK в Google Mobile Ads SDK.
Важно, чтобы ваше пользовательское событие пересылало как можно больше таких обратных вызовов, чтобы ваше приложение получало эквивалентные события от Google Mobile Ads SDK. Вот пример использования обратных вызовов:
На этом реализация пользовательских событий для нативной рекламы завершена. Полный пример доступен на GitHub .