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

המדריך הזה מיועד לבעלי אפליקציות שמשלבים מודעות בפתיחת אפליקציה.

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

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

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

  1. צריך ליצור כיתה של מנהל שטוענת מודעה לפני שצריך להציג אותה.
  2. הצגת התוסף במהלך אירועים בחזית האפליקציה.
  3. לטפל בקריאות חוזרות (callback) במצגת.

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

ביצוע בדיקות באמצעות מודעות בדיקה תמיד

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

הדרך הקלה ביותר לטעון מודעות בדיקה היא להשתמש במזהה הייעודי של יחידת מודעות לבדיקה עבור אפליקציה פתיחת מודעות:

ca-app-pub-3940256099942544/5575463023

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

מידע נוסף על אופן הפעולה של מודעות הבדיקה של Mobile Ads SDK זמין במאמר בדיקה מודעות.

הטמעת סוג מנהלים

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

יש ליצור כיתת סינגלטון חדשה בשם AppOpenAdManager ולמלא אותה כך ככה:

Swift

class AppOpenAdManager: NSObject {
  var appOpenAd: GADAppOpenAd?
  var isLoadingAd = false.
  var isShowingAd = false

  static let shared = AppOpenAdManager()

  private func loadAd() async {
    // TODO: Implement loading an ad.
  }

  func showAdIfAvailable() {
    // TODO: Implement showing an ad.
  }

  private func isAdAvailable() -> Bool {
    // Check if ad exists and can be shown.
    return appOpenAd != nil
  }
}

Objective-C

@interface AppOpenAdManager ()
@property(nonatomic, strong) GADAppOpenAd *appOpenAd;
@property(nonatomic, assign) BOOL isLoadingAd;
@property(nonatomic, assign) BOOL isShowingAd;

@end

@implementation AppOpenAdManager

+ (nonnull AppOpenAdManager *)sharedInstance {
  static AppOpenAdManager *instance = nil;
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    instance = [[AppOpenAdManager alloc] init];
  });
  return instance;
}

- (void)loadAd {
  // TODO: Implement loading an ad.
}

// Add this method to the .h file.
- (void)showAdIfAvailable {
  // TODO: Implement showing an ad.
}

- (BOOL)isAdAvailable {
  // Check if ad exists and can be shown.
  return self.appOpenAd != nil;
}

@end

טעינת מודעה

השלב הבא הוא למלא את ה-method loadAd().

Swift

private func loadAd() async {
  // Do not load ad if there is an unused ad or one is already loading.
  if isLoadingAd || isAdAvailable() {
    return
  }
  isLoadingAd = true

  do {
    appOpenAd = try await GADAppOpenAd.load(
      withAdUnitID: "ca-app-pub-3940256099942544/5575463023", request: GADRequest())
  } catch {
    print("App open ad failed to load with error: \(error.localizedDescription)")
  }
  isLoadingAd = false
}

Objective-C

- (void)loadAd {
  // Do not load ad if there is an unused ad or one is already loading.
  if (self.isLoadingAd || [self isAdAvailable]) {
    return;
  }
  self.isLoadingAd = YES;

  [GADAppOpenAd loadWithAdUnitID:@"ca-app-pub-3940256099942544/5575463023"
                       request:[GADRequest request]
             completionHandler:^(GADAppOpenAd *_Nullable appOpenAd, NSError *_Nullable error) {
               self.isLoadingAd = NO;
               if (error) {
                 NSLog(@"Failed to load app open ad: %@", error);
                 return;
               }
               self.appOpenAd = appOpenAd;
             }];
}

הצגת מודעה

השלב הבא הוא למלא את ה-method showAdIfAvailable(). אם אין מודעות זמין, השיטה מנסה לטעון מודעה.

Swift

func showAdIfAvailable() {
  // If the app open ad is already showing, do not show the ad again.
  guard !isShowingAd else { return }

  // If the app open ad is not available yet but is supposed to show, load
  // a new ad.
  if !isAdAvailable() {
    Task {
      await loadAd()
    }
    return
  }

  if let ad = appOpenAd {
    isShowingAd = true
    ad.present(fromRootViewController: nil)
  }
}

Objective-C

- (void)showAdIfAvailable {
  // If the app open ad is already showing, do not show the ad again.
  if (self.isShowingAd) {
    return;
  }

  // If the app open ad is not available yet but is supposed to show, load a
  // new ad.
  if (![self isAdAvailable]) {
    [self loadAd];
    return;
  }

  self.isShowingAd = YES;
  [self.appOpenAd presentFromRootViewController:nil];
}

הצגת המודעה במהלך אירועים בחזית האפליקציה

כשהאפליקציה הופכת לפעילה, צריך לקרוא ל-showAdIfAvailable() כדי להציג מודעה אם אחד זמין, או טוען דוח חדש.

Swift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  // ...

  func applicationDidBecomeActive(_ application: UIApplication) {
    // Show the app open ad when the app is foregrounded.
    AppOpenAdManager.shared.showAdIfAvailable()
  }
}

Objective-C

@implementation AppDelegate
// ...

- (void) applicationDidBecomeActive:(UIApplication *)application {
  // Show the app open ad when the app is foregrounded.
  [AppOpenAdManager.sharedInstance showAdIfAvailable];
}

@end

איך מטפלים בקריאות חוזרות (callback) במצגת

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

צריך להוסיף בכיתה AppOpenAdManager את פריטי המידע הבאים:

Swift

class AppOpenAdManager: NSObject, GADFullScreenContentDelegate {
  // ...

  private func loadAd() async {
    // Do not load ad if there is an unused ad or one is already loading.
    if isLoadingAd || isAdAvailable() {
      return
    }
    isLoadingAd = true

    do {
      appOpenAd = try await GADAppOpenAd.load(
        withAdUnitID: "ca-app-pub-3940256099942544/5575463023", request: GADRequest())
      appOpenAd?.fullScreenContentDelegate = self
    } catch {
      print("App open ad failed to load with error: \(error.localizedDescription)")
    }
    isLoadingAd = false
  }

  // ...

  // MARK: - GADFullScreenContentDelegate methods

  func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
    print("App open ad will be presented.")
  }

  func adDidDismissFullScreenContent(_ ad: GADFullScreenPresentingAd) {
    appOpenAd = nil
    isShowingAd = false
    // Reload an ad.
    Task {
      await loadAd()
    }
  }

  func ad(
    _ ad: GADFullScreenPresentingAd,
    didFailToPresentFullScreenContentWithError error: Error
  ) {
    appOpenAd = nil
    isShowingAd = false
    // Reload an ad.
    Task {
      await loadAd()
    }
  }
}

Objective-C

@interface AppOpenAdManager () <GADFullScreenContentDelegate>
@property(nonatomic, strong) GADAppOpenAd *appOpenAd
@property(nonatomic, assign) BOOL isLoadingAd;
@property(nonatomic, assign) BOOL isShowingAd;

@end

@implementation AppOpenAdManager

// ...

- (void)loadAd {
  // Do not load ad if there is an unused ad or one is already loading.
  if (self.isLoadingAd || [self isAdAvailable]) {
    return;
  }
  self.isLoadingAd = YES;

  [GADAppOpenAd loadWithAdUnitID:@"ca-app-pub-3940256099942544/5575463023"
                       request:[GADRequest request]
             completionHandler:^(GADAppOpenAd *_Nullable appOpenAd, NSError *_Nullable error) {
              self.isLoadingAd = NO;
               if (error) {
                 NSLog(@"Failed to load app open ad: %@", error);
                 return;
               }
               self.appOpenAd = appOpenAd;
               self.appOpenAd.fullScreenContentDelegate = self;
             }];
}

- (BOOL)isAdAvailable {
  // Check if ad exists and can be shown.
  return self.appOpenAd != nil;
}

// ...

#pragma mark - GADFullScreenContentDelegate methods

- (void)adWillPresentFullScreenContent:(nonnull id<GADFullScreenPresentingAd>)ad {
  NSLog(@"App open ad is will be presented.");
}

- (void)adDidDismissFullScreenContent:(nonnull id<GADFullScreenPresentingAd>)ad {
  self.appOpenAd = nil;
  self.isShowingAd = NO;
  // Reload an ad.
  [self loadAd];
}

- (void)ad:(nonnull id<GADFullScreenPresentingAd>)ad
    didFailToPresentFullScreenContentWithError:(nonnull NSError *)error {
  self.appOpenAd = nil;
  self.isShowingAd = NO;
  // Reload an ad.
  [self loadAd];
}

@end

כדאי לשקול את תפוגת המודעה

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

ב-AppOpenAdManager, מוסיפים נכס Date בשם loadTime ומגדירים את כשהמודעה שלך נטענת. לאחר מכן אפשר להוסיף שיטה שמחזירה את true, אם חלפו פחות ממספר מסוים של שעות מאז שהמודעה שלכם נטענה. לוודא אתם בודקים את תוקף ההפניה של המודעה לפני שאתם מנסים להציג אותה.

Swift

class AppOpenAdManager: NSObject, GADFullScreenContentDelegate {
  var appOpenAd: GADAppOpenAd?
  var isLoadingAd = false.
  var isShowingAd = false
  var loadTime: Date?
  let fourHoursInSeconds = TimeInterval(3600 * 4)

  // ...

  private func loadAd() async {
    // Do not load ad if there is an unused ad or one is already loading.
    if isLoadingAd || isAdAvailable() {
      return
    }
    isLoadingAd = true

    do {
      appOpenAd = try await GADAppOpenAd.load(
        withAdUnitID: "ca-app-pub-3940256099942544/5575463023", request: GADRequest())
      appOpenAd?.fullScreenContentDelegate = self
      loadTime = Date()
    } catch {
      print("App open ad failed to load with error: \(error.localizedDescription)")
    }
    isLoadingAd = false
  }

  private func wasLoadTimeLessThanFourHoursAgo() -> Bool {
    guard let loadTime = loadTime else { return false }
    // Check if ad was loaded more than four hours ago.
    return Date().timeIntervalSince(loadTime) < fourHoursInSeconds
  }

  private func isAdAvailable() -> Bool {
    // Check if ad exists and can be shown.
    return appOpenAd != nil && wasLoadTimeLessThanFourHoursAgo()
  }
}

Objective-C

static NSTimeInterval const fourHoursInSeconds = 3600 * 4;

@interface AppOpenAdManager () <GADFullScreenContentDelegate>
@property(nonatomic, strong) GADAppOpenAd *appOpenAd
@property(nonatomic, assign) BOOL isLoadingAd;
@property(nonatomic, assign) BOOL isShowingAd;
@property(weak, nonatomic) NSDate *loadTime;

@end

@implementation AppOpenAdManager

// ...

- (void)loadAd {
  // Do not load ad if there is an unused ad or one is already loading.
  if (self.isLoadingAd || [self isAdAvailable]) {
    return;
  }
  self.isLoadingAd = YES;

  [GADAppOpenAd loadWithAdUnitID:@"ca-app-pub-3940256099942544/5575463023"
                       request:[GADRequest request]
             completionHandler:^(GADAppOpenAd *_Nullable appOpenAd, NSError *_Nullable error) {
              self.isLoadingAd = NO;
               if (error) {
                 NSLog(@"Failed to load app open ad: %@", error);
                 return;
               }
               self.appOpenAd = appOpenAd;
               self.appOpenAd.fullScreenContentDelegate = self;
               self.loadTime = [NSDate date];
             }];
}

- (BOOL)wasLoadTimeLessThanFourHoursAgo {
  // Check if ad was loaded more than four hours ago.
  return [[NSDate Date] timeIntervalSinceDate:self.loadTime] < fourHoursInSeconds;
}

- (BOOL)isAdAvailable {
  // Check if ad exists and can be shown.
  return self.appOpenAd != nil && [self wasLoadTimeLessThanFourHoursAgo];
}

@end

מסכים להפעלה במצב התחלתי ולטעינה

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

דוגמה להפעלה במצב התחלתי (cold start) היא כשמשתמש פותח את האפליקציה בפעם הראשונה. כשמפעילים את התכונה 'הפעלה במצב התחלתי', אין מודעה בפתיחת אפליקציה שנטענה בעבר ומוכנה ל יוצגו מיד. הזמן שחלף בין שליחת הבקשה להצגת מודעה לבין קבלת המודעה עלול ליצור מצב שבו משתמשים יוכלו להשתמש באפליקציה לזמן קצר לפני מופתעים בעקבות מודעה שמוצגת מחוץ להקשר. יש להימנע מכך, מפני חוויית משתמש גרועה.

הדרך המועדפת לשימוש במודעות בפתיחת אפליקציה בזמן הפעלה במצב התחלתי (cold start) היא להשתמש במסך טעינה כדי לטעון את המשחק או את נכסי האפליקציה, ולהציג את המודעה רק בטעינה מסך. אם הטעינה של האפליקציה הסתיימה והיא שלחה את המשתמש תוכן של האפליקציה, לא להציג את המודעה.

שיטות מומלצות

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

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

הקישור המלא ב-GitHub

Swift Objective-C

השלבים הבאים

מידע נוסף על פרטיות המשתמשים