Chapter 15
Displaying Banner Ads using Google AdMob

Like most developers, you're probably looking for ways to make extra money from your app. The most straightforward way is to put your app in the App Store and sell it for $0.99 or more. This paid model works really well for some apps. However, this is not the only monetization model. In this chapter, we'll discuss how to monetize your app using Google AdMob.

But why Google AdMob? We're developing iOS apps. Why don't we use Apple's iAd?

Apple discontinued its iAd App Network on June 30, 2016. Therefore, you can no longer use iAd as your advertising solution for iOS apps. You have to look for other alternatives for placing banner ads.

Among all the mobile ad networks, it is undeniable that Google's AdMob is the most popular one. Similar to iAd, Google provides an SDK for developers to embed ads in their iOS app. Google sells the advertising space (e.g., banners) within your app to a bunch of advertisers. You earn ad revenue when a user views or clicks your ads.

To use AdMob in your apps, you will need to use the Google Mobile Ads SDK. The integration is not difficult. To display a simple ad banner, it just takes a few lines of code and you're ready to start making a profit from your app.

There is no better way to learn the AdMob integration than by trying it out. As usual, we'll work on a sample project and then add a banner ad. You can download the Xcode project template from http://www.appcoda.com/resources/swift59/GoogleAdDemoStarter.zip.

On top of the AdMob integration, you will also learn how to perform lazy loading in Swift.

Apply a Google AdMob Account

Before you can integrate your apps with Google AdMob, you'll need to first enroll into the AdMob service. Now open the link below using Safari or your favorite browser:

https://www.google.com/admob/

As AdMob is now part of Google, you can simply sign in with your Google account or register a new one. AdMob requires you to have a valid AdSense account and AdWords account. If you don't have one or both of these accounts, follow the sign-up process and connect them to your Google Account.

Figure 15.1. Sign into Google AdMob
Figure 15.1. Sign into Google AdMob

Once you finish the registration, you will be brought to the AdMob dashboard. In the navigation on your left, select the Apps option.

Figure 15.2. AdMob Dashboard
Figure 15.2. AdMob Dashboard

Here, choose the Add Your First App option. You will then need to choose the app platform, which is iOS. AdMob will also ask you if your app has been published on the App Store. Assuming your app has not been published, choose the option "No". We will register the app by filling in the form manually. In future, if you already have an app on the App Store, you can let AdMob retrieve your app information.

Figure 15.3. Creating a new app for AdMob
Figure 15.3. Creating a new app for AdMob

Set the app name to GoogleAdMobLiveDemo. Click Add App to proceed to the next step. You should see a confirmation message indicating the app is created successfully. You can then click the Done button to return to the App Overview screen.

Next, we need to create at least an ad unit. Click Add Ad Unit to proceed. In this demo, we use the banner ad. Select Banner and accept the default options. For the Ad unit name, set it to Banner Ad.

Figure 15.4. Create a banner ad
Figure 15.4. Create a banner ad

Click Create Ad Unit to generate the ad unit ID. This completes the configuration of your new app. You will find the App ID and Ad unit ID in the confirmation screen. Please save these information. We will need them in the later section when we integrate AdMob with our Xcode project.

Installing the Google Mobile Ads SDK

Before you can integrate with AdMob, you have to install the Google Mobile Ads SDK in your Xcode project. One simple way to import the SDK into the project is by using CocoaPods. We have a full chapter explaining what CocoaPods is and how you can use it. If you haven't read chapter 33, please refer to it first.

Assuming your Xcode project is saved in the Desktop folder, open Terminal and key in the following command to change folder:

cd ~/Desktop/GoogleAdDemo

Then create the Podfile by typing pod init. Open your project's Podfile and add this line to your app's target:

pod 'Google-Mobile-Ads-SDK'

Save the change and type the following command to install the SDK:

pod install

Using Google Mobile Ads Framework

Now that you have completed the configuration in AdMob and imported the SDK, let's move to the actual implementation. Fire up Xcode and open GoogleAdDemo.xcworkspace of the project. Please note that it is GoogleAdDemo.xcworkspace instead of GoogleAdDemo.xcodeproj. If you look closely at the project navigator, you find two projects: GoogleAdDemo and Pods. The former is the original project, while the Pods is the project that bundles the Google Mobile Ads SDK.

Figure 15.5. You can't run the app now
Figure 15.5. You can't run the app now

If you compile and run the project, it will end up with an error. This is normal because we haven't provided an application ID for the SDK. Later, we will make some changes and tweak it to show an advertisement.

To use the Google Mobile Ads SDK in your code, you will have to import the framework and register your App ID. We will do the initialization in the AppDelegate.swift file. Insert the import statement at the beginning of the file:

import GoogleMobileAds

Next, insert the following line of code in the application(_:didFinishLaunchingWithOptions:) method:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    GADMobileAds.sharedInstance().start(completionHandler: nil)

    return true
}

Initializing the Google Mobile Ads SDK at app launch allows the SDK to perform configuration tasks as early as possible. Next, open Info.plist and add a new row named GADApplicationIdentifier. Recall that AdMob created a unique application ID for your application, you have to set the ID in this entry. For me, I set it to:

ca-app-pub-6371581406920912~3037490636

Please make sure you replace the App ID with yours. Also, please add another entry for the SKAdNetworkItems key. To add these two keys, right click Info in the project navigator and select Open As > Source Code. This lets you edit the Info.plist file in the code editor.

Figure 15.6. Configuring the Info.plist file
Figure 15.6. Configuring the Info.plist file

Insert the following code in the file and place it before the last </dict>:

<key>GADApplicationIdentifier</key>
<string>ca-app-pub-6371581406920912~3037490636</string>
<key>SKAdNetworkItems</key>
  <array>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>cstr6suwn9.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>4fzdc2evr5.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>2fnua5tdw4.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>ydx93a7ass.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>5a6flpkh64.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>p78axxw29g.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>v72qych5uu.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>c6k4g5qg8m.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>s39g8k73mm.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>3qy4746246.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>3sh42y64q3.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>f38h382jlk.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>hs6bdukanm.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>prcb7njmu6.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>v4nxqhlyqp.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>wzmmz9fp6w.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>yclnxrl5pm.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>t38b2kh725.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>7ug5zh24hu.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>9rd848q2bz.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>n6fk4nfna4.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>kbd757ywx3.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>9t245vhmpl.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>4468km3ulz.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>2u9pt9hc89.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>8s468mfl3y.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>av6w8kgt66.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>klf5c3l5u5.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>ppxm28t8ap.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>424m5254lk.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>uw77j35x4d.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>578prtvx9j.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>4dzt52r2t5.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>e5fvkxwrpn.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>8c4e2ghe7u.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>zq492l623r.skadnetwork</string>
    </dict>
    <dict>
      <key>SKAdNetworkIdentifier</key>
      <string>3qcr597p9d.skadnetwork</string>
    </dict>
  </array>

You have to update the value of GADApplicationIdentifier with your own ad ID. That's it for the configuration.

Displaying Banner Ads at the Table View Header

Let's start with the simplest way to display a banner ad in your app. We will request an ad banner from Google and display the ad at the table header.

To display a banner ad at that position, all you need to do is create a GADBannerView object, set its delegate, and root view controller. Then you call its load method with an ad request to retrieve a banner ad. When the ad is ready to display, it will call the adViewDidReceiveAd(bannerView:) method of the GADBannerViewDelegate protocol. So you just need to implement the method to show the banner ad in the table view header.

Okay, let's now go into the implementation.

Now open NewsTableViewController.swift. First, import the GoogleMobileAds framework:

import GoogleMobileAds

Next, declare a variable of the type GADBannerView. This is the variable for holding the banner view:

lazy var adBannerView: GADBannerView = {
    let adBannerView = GADBannerView(adSize: GADPortraitAnchoredAdaptiveBannerAdSizeWithWidth(300))
    adBannerView.adUnitID = "ca-app-pub-8501671653071605/1166331146"
    adBannerView.delegate = self
    adBannerView.rootViewController = self

    return adBannerView
}()

In the code above, we use a closure to initialize the adBannerView variable, which is an instance of GADBannerView. During the initialization, we tell the SDK that we want to retrieve an adaptive banner (GADPortraitAnchoredAdaptiveBannerAdSizeWithWidth). Adaptive banners, as the name suggests, are ad units that are clever enough to detect the screen width and adjust its size accordingly. We also set the ad unit ID, delegate and root view controller. Again, please replace the ad unit ID with yours.

We use lazy initialization (sometimes it is called lazy instantiation or loading) to initialize the adBannerView variable. In Swift, you use the lazy keyword to indicate that the variable can be initialized later. More specificially, the variable will only be instantiated when it is used. This technique for delaying an object creation is especially useful when it takes a considerable time to load an object or the object you're referring to is not ready at the time of object creation. During initialization, we set the delegate and rootViewController properties to self. As the NewsTableViewController is not ready at the time, we use lazy to defer the initialization of adBannerView.

Is it a must to use lazy initialization for creating a banner view? No, I want to take this chance to introduce you lazy initialization, and demonstrate how to use a closure for variable initialization. You can do the same without using lazy initialization like this:

var adBannerView: GADBannerView?

override func viewDidLoad() {
    super.viewDidLoad()

    adBannerView = GADBannerView(adSize: kGADAdSizeSmartBannerPortrait)
    adBannerView?.adUnitID = "ca-app-pub-8501671653071605/1166331146"
    adBannerView?.delegate = self
    adBannerView?.rootViewController = self
}

However, as you can see, the former way of initialization allows us group all the initialization code in the closure. The code is more readable and manageable.

Now that we have created the adBannerView variable, the next thing is to request the ad. To do that, all you need to do is add the following lines of code in the viewDidLoad method:

GADMobileAds.sharedInstance().requestConfiguration.testDeviceIdentifiers = [ GADSimulatorID ]
adBannerView.load(GADRequest())

To load a production ad on a test environment, Google requires you to set your test device. This is the purpose of the first line of the code.

You may wonder why you need to define the test devices. What if you omit that line of code? Your app may work and display ads. But it's Google's policy that you have to comply to.

Once you register an app in the AdMob UI and create your own ad unit IDs for use in your app, you'll need to explicitly configure your device as a test device when you're developing. This is extremely important. Testing with real ads (even if you never tap on them) is against AdMob policy and can cause your account to be suspended.

- AdMob Integration Guide

Lastly, we need to adopt the GADBannerViewDelegate protocol. We will create an extension to adopt the protocol and implement two optional methods like this:

extension NewsTableViewController: GADBannerViewDelegate {

    func bannerViewDidReceiveAd(_ bannerView: GADBannerView) {
        print("Banner loaded successfully")
        tableView.tableHeaderView?.frame = bannerView.frame
        tableView.tableHeaderView = bannerView
    }

    func bannerView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: Error) {

        print("Fail to receive ads")
        print(error)
    }

}

When the ad is successfully loaded, the bannerViewDidReceiveAd method is called. In the method, we simply assign the banner view to the table's header view. This allows the app to show the banner ad in the table header. If the ad is failed to load, we just print the error message to console.

Try to run the demo app and play around with it. When the app is launched, you will see a banner ad at the top of the table view.

Figure 15.7. Banner ads at the table view header
Figure 15.7. Banner ads at the table view header

*Note: If your app fails to retrieve the ad, please try to change the value of adUnitId to ca-app-pub-3940256099942544/2934735716, which is the demo ad provided by Google. Sometimes it takes time for Google to enable your ad unit, you can use the demo ad ID for testing purpose.*

Adding a Subtle Animation

Sometimes adding a subtle animation to banner ads can give a better user experience about how the ad transitions onto the screen. In this section, I will show you how to animate the banner ad. We will add a slide-down animation when the ad transitions onto the screen.

The trick is to apply UIView animations to the ad banner. When the ad is first loaded, we reposition the ad banner off the screen. Then we bring it back using a slide down animation.

As mentioned before, the bannerViewDidReceiveAd method is called when an ad is ready. To animate the ad banner, all we need to do is modify the method like this:

func bannerViewDidReceiveAd(_ bannerView: GADBannerView) {
    print("Banner loaded successfully")

    // Reposition the banner ad to create a slide down effect
    let translateTransform = CGAffineTransform(translationX: 0, y: -bannerView.bounds.size.height)
    bannerView.transform = translateTransform

    UIView.animate(withDuration: 0.5) {
        self.tableView.tableHeaderView?.frame = bannerView.frame
        bannerView.transform = CGAffineTransform.identity
        self.tableView.tableHeaderView = bannerView
    }
}

We first create a translateTransform to move the banner view off the screen. We then call UIView.animate to slide the banner down onto the screen.

Run the project again to test the app. The ad will be displayed with an animated effect.

Figure 15.8. Animating the ad banner
Figure 15.8. Animating the ad banner

Displaying a Sticky Banner Ad

As you scroll through the table view, the ad banner disappears. It doesn't stick to the table header. You may wonder how you can display a sticky banner ad. That's what we're going to explore in this section.

The banner ad is now inserted into the table header view. If you want to make it sticky, you can add it to the section's header view instead of the table's header view.

Let's see how to implement it.

Insert the following methods in the NewsTableViewController class:

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    return adBannerView
}

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {

    return adBannerView.frame.height
}

We override the default tableView(_:viewForHeaderInSection:) method with our own method to return the ad banner view.

The default height of the header is too small for the ad banner. So we also override the tableView(_:heightForHeaderInSection:) method and return the height of the banner view frame.

Lastly, modify the bannerViewDidReceiveAd method like this:

func bannerViewDidReceiveAd(_ bannerView: GADBannerView) {
    print("Banner loaded successfully")

    // Reposition the banner ad to create a slide down effect
    let translateTransform = CGAffineTransform(translationX: 0, y: -bannerView.bounds.size.height)
    bannerView.transform = translateTransform

    UIView.animate(withDuration: 0.5) {
        bannerView.transform = CGAffineTransform.identity
    }
}

We just remove those lines of code that are related to table view header, which are no longer necessary.

That's it. It is now ready to test the app again. The ad banner displays at the fixed position.

Working with Interstitial Ads

Not only can you include banner ads in your apps, but the Google Mobile Ads SDK also lets you easily display interstitial ads (i.e. full screen ads). Typically you can earn more ad revenue through interstitial ads as it completely blocks out the app's content and catches users' attention.

The downside of this kind of mobile ad is sometimes irritating as it forces users to view the ad until they click out. But it really depends how frequent and at what point you display the full screen ad. I have used some apps that keep displaying interstitial ads every couple of minutes. A well-thought ad placement can make your app less irritating. For example, you only display an ad once or between game levels if you're developing a game. Anyway, my focus here is to show you how to display an interstial ad in iOS apps. My plan is to display the ad right after a user launches the demo app.

To do that, you have to first go back to AdMob's dashboard (https://apps.admob.com) to create an interstial ad for the demo app. Select Apps in the side menu and choose GoogleAdMobLiveDemo. In the next screen, click Add Ad Unit to create a new ad unit and choose Interstitial.

Figure 15.9. Adding a new Interstitial ad unit
Figure 15.9. Adding a new Interstitial ad unit

This time, we create an interstitial ad. Give the ad unit a name and then click Create Ad Unit to create the unit. AdMob should generate another ad unit ID for you.

Now go back to the Xcode project.

The code of implementing an interstitial ad is very similar to that of a banner ad. Instead of using the GADBannerView class, you use the GADInterstitialAd class. So, declare a variable for storing the GADInterstitialAd object in the NewsTableViewController class:

var interstitial: GADInterstitialAd?

However, one main difference between GADBannerView and GADInterstitialAd is that GADInterstitialAd is a one time use object. That means the interstitial can't be used to load another ad once it is shown.

Due to this reason, we create a helper method called loadInterstitialAd() to create the ad. Insert the method in the NewsTableViewController class:

private func loadInterstitialAd() {
    let request = GADRequest()
    GADInterstitialAd.load(withAdUnitID: "ca-app-pub-8501671653071605/5691915429", request: request) { ad, error in

        if error != nil { return }

        self.interstitial = ad
        self.interstitial?.fullScreenContentDelegate = self
        self.interstitial?.present(fromRootViewController: self)
    }

}

We first initialize a GADRequest object. Then we create a GADInterstitialAd object, call its load method with our ad unit ID and the ad request. When the ad is loaded, we present the ad in the completion handler block. The interstitial ad allows you to set a delegate for further processing. Here, we set the delegate to self.

We will create the ad when the view is loaded. Insert the following line of code in the viewDidLoad() method:

loadInterstitialAd()

Similar to GADBannerView, we need to adopt a protocol in order to check the status of an ad. Create an extension to implement the GADFullScreenContentDelegate protocol:

extension NewsTableViewController: GADFullScreenContentDelegate {

    func adWillPresentFullScreenContent(_ ad: GADFullScreenPresentingAd) {
        print("Interstitial ad loaded successfully")
    }

    func ad(_ ad: GADFullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) {
        print("Failed to receive interstitial ads")
    }
}

Now you're ready to test the app. After launching the app, you should see a full-screen test ad (or other test ad provided by Google).

Figure 15.11. Adding an interstitial ad unit
Figure 15.11. Adding an interstitial ad unit

To continue reading and access the full version of the book, please get the full copy here. You will also be able to access the full source code of the project.

results matching ""

    No results matching ""