Объявления с вознаграждением

Объявления с вознаграждением – это реклама, с которой пользователи могут взаимодействовать в обмен на вознаграждение в приложении. В этом руководстве рассказывается, как интегрировать в приложение для iOS рекламу с вознаграждением из AdMob. Ознакомьтесь с историями успеха клиентов: история 1, история 2.

Требования

Прежде чем продолжить, настройте Google Mobile Ads SDK.

Всегда тестируйте с помощью тестовых объявлений

При создании и тестировании приложений используйте тестовые объявления, а не реальные. В противном случае ваш аккаунт может быть заблокирован.

Самый простой способ загрузить тестовые объявления – использовать специальный идентификатор тестового рекламного блока для объявлений с вознаграждением в iOS:

ca-app-pub-3940256099942544/1712485313

Он специально настроен так, чтобы возвращать тестовые объявления для каждого запроса, и вы можете использовать его в своих приложениях при написании кода, тестировании и отладке. Не забудьте заменить его на идентификатор своего рекламного блока перед публикацией приложения.

Подробнее о том, как работают тестовые объявления Google Mobile Ads SDK, можно узнать в статье Test Ads.

Реализация

Чтобы интегрировать рекламу с вознаграждением, выполните следующие основные действия:

  • Как загрузить объявление
  • [Необязательно] Проверка обратных вызовов SSV
  • Как зарегистрироваться для получения обратных вызовов
  • Показать объявление и обработать событие получения вознаграждения

Как загрузить объявление

Объявление загружается с помощью метода load(adUnitID:request) класса GADRewardedAd.

Swift

func loadRewardedAd() async {
  do {
    rewardedAd = try await RewardedAd.load(
      // Replace this ad unit ID with your own ad unit ID.
      with: "ca-app-pub-3940256099942544/1712485313", request: Request())
    rewardedAd?.fullScreenContentDelegate = self
  } catch {
    print("Rewarded ad failed to load with error: \(error.localizedDescription)")
  }
}

SwiftUI

import GoogleMobileAds

class RewardedViewModel: NSObject, ObservableObject, FullScreenContentDelegate {
  @Published var coins = 0
  private var rewardedAd: RewardedAd?

  func loadAd() async {
    do {
      rewardedAd = try await RewardedAd.load(
        with: "ca-app-pub-3940256099942544/1712485313", request: Request())
      rewardedAd?.fullScreenContentDelegate = self
    } catch {
      print("Failed to load rewarded ad with error: \(error.localizedDescription)")
    }
  }

Objective-C

// Replace this ad unit ID with your own ad unit ID.
[GADRewardedAd loadWithAdUnitID:@"ca-app-pub-3940256099942544/1712485313"
              request:[GADRequest request]
    completionHandler:^(GADRewardedAd *ad, NSError *error) {
      if (error) {
        NSLog(@"Rewarded ad failed to load with error: %@", [error localizedDescription]);
        return;
      }
      self.rewardedAd = ad;
      self.rewardedAd.fullScreenContentDelegate = self;
    }];

[Необязательно] Проверка обратных вызовов проверки на стороне сервера

Приложения, которым требуются дополнительные данные в обратных вызовах проверки на стороне сервера, должны использовать функцию специальных данных в объявлениях с вознаграждением. Любое строковое значение, заданное в объекте объявления с вознаграждением, передается в параметр запроса custom_data обратного вызова SSV. Если значение специальных данных не задано, значение параметра запроса custom_data не будет присутствовать в обратном вызове SSV.

В приведенном ниже фрагменте кода показано, как задать специальные данные для объекта объявления с вознаграждением перед отправкой запроса объявления:

Swift

private func validateServerSideVerification() async {
  do {
    rewardedAd = try await RewardedAd.load(
      // Replace this ad unit ID with your own ad unit ID.
      with: "ca-app-pub-3940256099942544/1712485313", request: Request())
    let options = ServerSideVerificationOptions()
    options.customRewardText = "SAMPLE_CUSTOM_DATA_STRING"
    rewardedAd?.serverSideVerificationOptions = options
  } catch {
    print("Rewarded ad failed to load with error: \(error.localizedDescription)")
  }
}

Objective-C

// Replace this ad unit ID with your own ad unit ID.
[GADRewardedAd loadWithAdUnitID:@"ca-app-pub-3940256099942544/1712485313"
                        request:[GADRequest request]
              completionHandler:^(GADRewardedAd *ad, NSError *error) {
                if (error) {
                  NSLog(@"Rewarded ad failed to load with error: %@", error.localizedDescription);
                  return;
                }
                self.rewardedAd = ad;
                GADServerSideVerificationOptions *options =
                    [[GADServerSideVerificationOptions alloc] init];
                options.customRewardString = @"SAMPLE_CUSTOM_DATA_STRING";
                ad.serverSideVerificationOptions = options;
              }];

Замените SAMPLE_CUSTOM_DATA_STRING собственными данными.

Как зарегистрироваться для получения обратных вызовов

Чтобы получать уведомления о событиях презентации, необходимо назначить GADFullScreenContentDelegate свойству fullScreenContentDelegate возвращенного объявления:

Swift

rewardedAd?.fullScreenContentDelegate = self

SwiftUI

rewardedAd?.fullScreenContentDelegate = self

Objective-C

self.rewardedAd.fullScreenContentDelegate = self;

Протокол GADFullScreenContentDelegate обрабатывает обратные вызовы, когда объявление показывается успешно или нет, а также когда оно закрывается. Ниже приведен пример кода, в котором реализован протокол:

Swift

func adDidRecordImpression(_ ad: FullScreenPresentingAd) {
  print("\(#function) called.")
}

func adDidRecordClick(_ ad: FullScreenPresentingAd) {
  print("\(#function) called.")
}

func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) {
  print("\(#function) called.")
}

func adWillDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
  print("\(#function) called.")
}

func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
  print("\(#function) called.")
  // Clear the rewarded ad.
  rewardedAd = nil
}

func ad(
  _ ad: FullScreenPresentingAd,
  didFailToPresentFullScreenContentWithError error: Error
) {
  print("\(#function) called with error: \(error.localizedDescription).")
}

SwiftUI

func adDidRecordImpression(_ ad: FullScreenPresentingAd) {
  print("\(#function) called")
}

func adDidRecordClick(_ ad: FullScreenPresentingAd) {
  print("\(#function) called")
}

func ad(
  _ ad: FullScreenPresentingAd,
  didFailToPresentFullScreenContentWithError error: Error
) {
  print("\(#function) called")
}

func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) {
  print("\(#function) called")
}

func adWillDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
  print("\(#function) called")
}

func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) {
  print("\(#function) called")
  // Clear the rewarded ad.
  rewardedAd = nil
}

Objective-C

- (void)adDidRecordImpression:(id<GADFullScreenPresentingAd>)ad {
  NSLog(@"%s called", __PRETTY_FUNCTION__);
}

- (void)adDidRecordClick:(id<GADFullScreenPresentingAd>)ad {
  NSLog(@"%s called", __PRETTY_FUNCTION__);
}

- (void)adWillPresentFullScreenContent:(id<GADFullScreenPresentingAd>)ad {
  NSLog(@"%s called", __PRETTY_FUNCTION__);
}

- (void)adWillDismissFullScreenContent:(id<GADFullScreenPresentingAd>)ad {
  NSLog(@"%s called", __PRETTY_FUNCTION__);
}

- (void)adDidDismissFullScreenContent:(id<GADFullScreenPresentingAd>)ad {
  NSLog(@"%s called", __PRETTY_FUNCTION__);
  // Clear the rewarded ad.
  self.rewardedAd = nil;
}

- (void)ad:(id)ad didFailToPresentFullScreenContentWithError:(NSError *)error {
  NSLog(@"%s called with error: %@", __PRETTY_FUNCTION__, error.localizedDescription);
}

Показать объявление и обработать событие получения вознаграждения

Перед показом объявления с вознаграждением пользователь должен явно согласиться на просмотр содержания объявления с вознаграждением в обмен на вознаграждение. Показ объявлений с вознаграждением всегда должен быть добровольным.

При показе объявления необходимо предоставить объект GADUserDidEarnRewardHandler, чтобы пользователь мог получить вознаграждение.

Ниже приведен код, который лучше всего подходит для показа объявлений с вознаграждением:

Swift

rewardedAd.present(from: self) {
  let reward = rewardedAd.adReward
  print("Reward received with currency \(reward.amount), amount \(reward.amount.doubleValue)")

  // TODO: Reward the user.
}

SwiftUI

Отслеживайте события пользовательского интерфейса в представлении, чтобы определить, когда показывать объявление.

var body: some View {
  VStack(spacing: 20) {
      Button("Watch video for additional 10 coins") {
        viewModel.showAd()
        showWatchVideoButton = false
      }

Покажите объявление с вознаграждением из модели представления:

func showAd() {
  guard let rewardedAd = rewardedAd else {
    return print("Ad wasn't ready.")
  }

  rewardedAd.present(from: nil) {
    let reward = rewardedAd.adReward
    print("Reward amount: \(reward.amount)")
    self.addCoins(reward.amount.intValue)
  }
}

Objective-C

[self.rewardedAd presentFromRootViewController:self
                      userDidEarnRewardHandler:^{
                        GADAdReward *reward = self.rewardedAd.adReward;
                        NSString *rewardMessage = [NSString
                            stringWithFormat:@"Reward received with currency %@ , amount %lf",
                                             reward.type, [reward.amount doubleValue]];
                        NSLog(@"%@", rewardMessage);

                        // TODO: Reward the user.
                      }];

Часто задаваемые вопросы

Можно ли узнать подробности о награде за GADRewardedAd?
Да. Если вам нужно узнать размер вознаграждения до того, как будет вызван userDidEarnRewardобратный вызов, в GADRewardedAd есть свойство adReward, которое позволяет проверить размер вознаграждения после загрузки объявления.
Есть ли время ожидания для вызова инициализации?
Через 10 секунд Google Mobile Ads SDK вызывает GADInitializationCompletionHandler, предоставленный методу startWithCompletionHandler:, даже если сеть медиации ещё не завершила инициализацию.
Что делать, если некоторые сети медиации не готовы, когда я получаю обратный вызов инициализации?

Мы рекомендуем загружать объявление в теге GADInitializationCompletionHandler. Даже если сеть медиации не готова, Google Mobile Ads SDK все равно отправляет ей запрос объявления. Поэтому, если инициализация сети медиации завершится после истечения времени ожидания, она все равно сможет обрабатывать будущие запросы объявлений в этом сеансе.

Вы можете продолжать опрашивать статус инициализации всех адаптеров в течение сеанса работы с приложением, вызывая GADMobileAds.initializationStatus.

Как узнать, почему та или иная сеть медиации не готова?

Свойство description объекта GADAdapterStatus описывает, почему адаптер не готов обрабатывать запросы объявлений.

Всегда ли обработчик завершения userDidEarnRewardHandler вызывается до метода делегата adDidDismissFullScreenContent:?

Для объявлений Google все звонки userDidEarnRewardHandler происходят до adDidDismissFullScreenContent:. Для объявлений, которые показываются с помощью медиации, порядок обратных вызовов определяется реализацией SDK сторонней рекламной сети. Если в SDK рекламной сети есть только один метод делегирования с информацией о вознаграждении, адаптер медиации вызывает userDidEarnRewardHandler до adDidDismissFullScreenContent:.

Примеры на GitHub

Посмотреть примеры объявлений с вознаграждением на нужном языке можно по ссылкам ниже.

Дальнейшие действия

Подробнее о конфиденциальности пользователей…