There are lots of ways to turn a profit from an app. One of the most common and effective ones is in-app advertisement.
Google is by far the biggest player in the online advertising game. Google AdMob is a service that provides highly personalized ads from over one million advertisers along with useful tools and analytics to be used in apps. Integrating Google AdMob into your Flutter apps is absolutely free and, as you'll learn in this tutorial, really simple.
The Finished App
Earlier this year, Google announced the release of a new Google Mobile Ads for Flutter plugin. This plugin combines the ability to display ads from Google AdMob as well as Google Ad Manager in multiple formats on both Android and iOS.
At the end of this tutorial, we are going to have a mock news app which will display several ad formats. The home page of the app will feature an inline banner ad within the newsfeed and a banner ad at the bottom of the screen.
The last ad format we are going to implement will be an interstitial ad. When clicking on a news story tile, you'll be taken to the news article page, but before seeing the article you'll see an interstitial ad. An interstitial ad is displayed as a full-screen overlay. In our implementation we are going to display a video ad which can be dismissed after 5 seconds. When the ad is dismissed, you'll see the news article page.
After completing this tutorial, you will have all of the knowledge you need to start displaying ads in your apps.
Getting Started
In this tutorial you are going to learn several things. First, you'll learn the basics of setting up your AdMob account. You will also learn how to set up platform specific configurations for your Flutter project to be able to display ads on Android and iOS. Then we'll go over configuring and displaying banner and interstitial ads in various places within the app.
We'll be working with a starter project that will have all of the core UI elements preconfigured for you. You can grab the starter project as well as the finished project from the links below.
Before we begin, let’s add the dependency for the Google Mobile Ads for Flutter plugin to the starter project.
We are going to be using the most current version of the plugin available at the time of writing this tutorial. So, if you are going through this lesson in the future, be mindful of any potential breaking changes that may occur. Go ahead and add version 0.13.3 to the starter project's pubspec.yaml file now.
pubspec.yaml
dependencies:
flutter:
sdk: flutter
google_mobile_ads: ^0.13.3
Starter Project Overview
The starter project is a simple mock UI of a news app. In this section we are going to go over all of the included files and assets.
In the lib folder you will find the main.dart file that contains an AppWidget
which returns a MaterialApp
that contains the HomePage
widget as the home
argument.
This project contains a few different files, so we separated them into two folders to keep things a bit more tidy. In the data folder you'll find the news_article.dart file. Here we’ve got a NewsArticle
class which holds a static field of type List
. This field contains a List
of NewsArticle
objects that we use to mock the news articles inside the app. Every NewsArticle
object holds a goofy news headline (just for fun) and a corresponding asset image path.
In the presentation folder you'll find three files - home_page.dart, news_article_page.dart, and widgets.dart. The home_page.dart contains a stateful HomePage
widget. This is the main page of the app and it displays a Scaffold
that has an AppBar
with a title and a ListView.builder
in the body. The ListView.builder
uses the static articles
field from the NewsArticle
class located in the news_article.dart file to generate custom ArticleTile
widgets. Every generated tile is wrapped in a GestureDetector
widget. Lastly, for the onTap
argument we’ve implemented a function that will route you to the NewsArticlePage
when the tile is tapped.
The news_article_page.dart contains a stateless widget which will dynamically display a mock news article depending on which tile in the home page was tapped. This NewsArticlePage
widget accepts a title and an image path through its constructor and displays them on the page along with some placeholder text.
The last file in the presentation folder is widgets.dart. This file contains two widgets - AppBarTitle
and ArticleTile
. The primary purpose of this file is to declutter our other pages.
We've gone over all of the files included in the starter project. The only thing left to mention is the assets folder. This folder holds all of the images we are displaying in our mock news articles.
Well, that's all for the starter project! Next we are going to go over creating and setting up an AdMob account.
Creating & Setting Up Your AdMob Account
When your app is in development, you should always use test ads instead of real ads. This is extremely important and shouldn't be overlooked. If you use real ads then advertisers will be charged for every click you make. If you click on the real ads too many times, Google will flag this activity as invalid and you risk being penalized for it. Even though we'll be using test ads in this tutorial, we'll still learn how to set up your AdMob account. This way when you are done developing you can swap out the test ads for your own.
Head over to admob.google.com and sign up if you don’t have an account , or sign in if you do. You'll need a Google account to create an AdMob account. When you sign up you will be taken through a few basic steps and will be asked to select things like your location, time zone and billing currency.
Creating an App
When you're done with the sign-up process, you'll see your user dashboard. If you created a brand new account then you can click “Get Started” or go to Apps in the left sidebar and then click “Add Your First App”.
From here you can choose to create an Android or iOS app. Since we are developing with Flutter you will likely want to create both. The steps for both are exactly the same. So, go ahead and create them now.
You'll be asked if your app is listed on an app store. If it isn’t, make sure to select “No”. Keep in mind that before your app can show ads, it'll need to go through Google’s approval process. This usually takes a couple of days.
Then you'll be prompted to choose a name for your app. On the same page you can also choose whether or not you want to use metrics. Metrics provide you with some useful data that will help you understand aggregated user behavior in your app. If you are serious about making money from ads, definitely enable this.
That’s it! Make sure you go through this process for both iOS and Android and you are good to move on to the next step.
Creating an Ad Unit
The next thing we need to do is create an ad unit. You should create an ad unit for every activity or location where you want to display the ads in your app. This is best practice because it'll allow you to individually track the performance of every ad unit. These units send requests to AdMob for ads and then display them in your app.
Each app will have its own ad units. So select either the Android or iOS app through the Apps menu in the sidebar and click on “Ad units”. Then click “Get Started”.
The next step is to select the ad format for this new unit. You can choose from several formats here depending on your needs. We are going to be creating banner and interstitial ads in this tutorial. The set-up process is identical for each ad format except for the rewarded ads. That is because for rewarded ads you also need to specify the reward amount and reward item name.
Go ahead and select the banner ad format. Then you'll be able to enter a name for your ad unit and change any advanced settings if necessary. Once you’re done, go ahead and click “Create ad unit”.
That’s it, you’re all done! At the end of the set-up you'll see an app ID and an ad unit ID. In production these are the values you should add into your app. We will go over where you need to add them in your Flutter project shortly. In the future, you can also click on “Apps” in the sidebar and select “View All Apps” to get the app IDs. To get the ad unit IDs you need to select either an iOS or an Android app and view their respective ad units by clicking on “Ad units” in the sidebar.
Configuring & Initializing AdMob in a Flutter Project
Now that we know how to start the monetization process through your AdMob dashboard, let’s configure our Flutter project to be able to display ads.
iOS Configuration
First, let’s configure the iOS side of things. Head over to iOS>Runner>Info.plist. You need to add some code in here. We added it at the top following the <plist version="1.0">
and the <dict>
tag.
Info.plist
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-3940256099942544~1458002511</string>
<key>SKAdNetworkItems</key>
<array>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>cstr6suwn9.skadnetwork</string>
</dict>
</array>
Here, the GADApplicationIdentifier
holds a string value with the AdMob app ID for your iOS app that you created in the AdMob dashboard earlier. You can add your own app ID here, but for this tutorial we are adding Google’s sample app ID. The other thing we added here is the SKAdNetworkIdentifier
and the string value here should stay exactly the same as shown in the snippet as it isn't specific to your AdMob account.
Android Configuration
Now, let’s configure our Android app. First, we need to make sure that the minSdkVersion
is 19 or higher, otherwise you will get an error. To change it go to android>app>build.gradle and scroll down a bit to find the minSdkVersion
.
Next, we need to add some code to the AndroidManifest.xml . To do this go to android>app>src>main>AndroidManifest.xml and add the following code.
AndroidManifest.xml
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713"/>
You can add this meta tag at the bottom of the file, right above the closing application
tag. The android:value
here should hold the string with your Android app ID that you can get from your AdMob dashboard. Once again, though, we are using a sample ID here provided by Google.
SDK Initialization
The last thing we are going to do in this section is initialize the Mobile Ads SDK. You must do this before you can start displaying ads. Luckily, initialization is incredibly simple. Head over to the main.dart file and import the plugin at the top. Now, in the main function right above runApp
add the following two lines of code.
main.dart
void main() {
WidgetsFlutterBinding.ensureInitialized();
MobileAds.instance.initialize();
runApp(AppWidget());
}
That's all! Next, we are going to set up an easy way to fetch appropriate ad unit IDs based on the requested ad format and platform your app is running on.
Creating an AdHelper Class
In the app we are creating we want to display two types of ad formats - banner and interstitial. We're also using Flutter, which means we are creating an iOS and an Android app at the same time. What we need to do now is be able to retrieve the correct ad unit ID for the specific platform and ad format. To achieve this, we are going to create an AdHelper
class. Create a new file in the lib>data folder and name it ad_helper.dart. Then add the following code to it.
ad_helper.dart
class AdHelper {
static String get bannerAdUnitId {
if (Platform.isAndroid) {
return "ca-app-pub-3940256099942544/6300978111";
} else if (Platform.isIOS) {
return "ca-app-pub-3940256099942544/2934735716";
} else {
throw new UnsupportedError("Unsupported platform");
}
}
static String get interstitialAdUnitId {
if (Platform.isAndroid) {
return "ca-app-pub-3940256099942544/8691691433";
} else if (Platform.isIOS) {
return "ca-app-pub-3940256099942544/5135589807";
} else {
throw new UnsupportedError("Unsupported platform");
}
}
}
As you can see here, we have a class with two static getters. One to get the banner ad unit IDs and the other to get the interstitial ad unit IDs. We check if the platform is iOS or Android using the dart:io import and return the appropriate ad unit ID for each ad format. In the case where the platform doesn't resolve to be either iOS or Android we throw an error. Remember, we are using the test ad unit IDs here. You can get the test ad units for every format for iOS here and for Android here. Once your app is ready to be published, you can replace these ad unit IDs with the ones you created in your AdMob dashboard.
Displaying a Bottom Banner Ad
It’s finally time to add our first ad. This will be a banner ad and we will display it at the bottom of the screen. It will always be visible to the user, even as they are scrolling through the page.
Setting up Variables and Functions
Before the user can see the ad, it needs to be created and then loaded. First, let’s import the Google Mobile Ads for Flutter plugin into the home_page.dart file and create a late
variable that will hold the reference to the ad we'll create. This variable will be of type BannerAd
, as that is exactly the object it will reference.
home_page.dart
class _HomePageState extends State<HomePage> {
late BannerAd _bottomBannerAd;
...
Now, we want to be able to check if the ad is loaded before displaying it. So let’s create a variable of type bool
to help us out with this. We will initially set it to false
. That's because at the very beginning the ad won’t be loaded and we only want it to be set to true
when it is.
home_page.dart
class _HomePageState extends State<HomePage> {
...
bool _isBottomBannerAdLoaded = false;
...
Next we are going to write a function that will create and load the banner ad for us when called.
home_page.dart
class _HomePageState extends State<HomePage> {
...
void _createBottomBannerAd() {
_bottomBannerAd = BannerAd(
adUnitId: AdHelper.bannerAdUnitId,
size: AdSize.banner,
request: AdRequest(),
listener: BannerAdListener(
onAdLoaded: (_) {
setState(() {
_isBottomBannerAdLoaded = true;
});
},
onAdFailedToLoad: (ad, error) {
ad.dispose();
},
),
);
_bottomBannerAd.load();
}
...
Let’s take a deeper look at what’s happening here. We are creating a BannerAd
object and initializing the _bottomBannerAd
variable with it. We are passing in several arguments to create the BannerAd
object, let’s go over them now.
You can see we are using the AdHelper
class we created earlier to get the banner ad unit ID. Then, we are specifying the dimensions for our ad. Adsize.banner
will return an ad that is sized 320X50dp.
To display ads we need to make an ad request, so here we are providing an AdRequest
object as an argument to do just that. We aren't providing any arguments to the AdRequest
constructor in our implementation, but you can provide things such as a List
of keywords here. This can be useful if you want to request ads which match the keywords you specify.
We are using BannerAdListener
to listen to the ad’s lifecycle events and perform some logic when they occur. We're listening to onAdLoaded
to find out when an ad loads and when it does we set our _isBottomBannerAdLoaded
variable to true
. We also listen to onAdFailedToLoad
. So if the ad fails to load, we call the dispose
method on it to make sure we free up the resources it is taking up. It's important to remember to call dispose
here, so make sure you make this a habit. In your own implementations you can also listen to other events, such as when an ad is opened, closed or when an ad receives an impression.
We’ve covered all of the details for creating a BannerAd
object. However, there's one more thing we are doing in our _createBottomBannerAd
function that we haven’t covered yet. At the very end you can see we are calling the load
method on _bottomBannerAd
. This will load the ad we created. When the ad is loaded, the _isBottomBannerAdLoaded
will be set to true
and then we can finally display the ad.
Before we can add the ad into our widget tree, there are two more things we need to do. First, we need to call the _createBottomBannerAd
function from the initState
of _HomePageState
. That is because we need the ad to load and be ready to be displayed when the user reaches this page.
home_page.dart
@override
void initState() {
super.initState();
_createBottomBannerAd();
}
The last thing we need to do is call dispose
on _bottomBannerAd
inside of the _HomePageState
dispose
method. This will ensure that we free up the resources when they are no longer needed.
home_page.dart
@override
void dispose() {
super.dispose();
_bottomBannerAd.dispose();
}
Displaying the Ad in the Widget Tree
Finally, we can add our ad to the page. If you want to have a banner ad that's fixed to the bottom of the screen, there are two easy ways to do this. If your app doesn’t have a bottom navigation bar, then you can add the AdWidget
as the bottomNavigationBar
argument of the Scaffold
. If you do have a bottom nav bar, you can instead add it as a persistentFooterButtons
argument of the Scaffold
. This will place it above the bottom navigation bar. Since our app doesn’t have a bottom nav, we are going to add our ad to the bottomNavigationBar
.
home_page.dart
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: _isBottomBannerAdLoaded
? Container(
height: _bottomBannerAd.size.height.toDouble(),
width: _bottomBannerAd.size.width.toDouble(),
child: AdWidget(ad: _bottomBannerAd),
)
: null,
...
The first thing we are doing here, is checking to make sure that the _isBottomBannerAdLoaded
is set to true
, which would mean our ad is loaded and ready to be displayed. If that's the case, then we return an AdWidget
wrapped in a Container
. If the ad isn’t loaded, we just set the bottomNavigationBar
to null
, which is its default value anyway.
You should wrap the AdWidget
in something like a Container
and specify the height
and width
. If you don’t do that, the ad will take up the entire screen. We are using the size
property of our _bottomBannerAd
to specify the height
and width
. For the AdWidget
itself, all we are doing is providing the _bottomBannerAd
we created as an ad
argument.
That’s it! Save your work, restart the app, and you should see the ad at the bottom of the screen. Next we are going to add another banner ad, but this time it'll show up inside of our ListView
.
Displaying an Inline Banner Ad
Showing an inline banner ad involves a few extra steps. Since we are already familiar with the simpler implementation, this should be easy.
Setting up Variables and Functions
First, we are going to create three variables. One is for the index at which we want our ad to be displayed inside the ListView
. In our app we are going to set that to 3. Then we need to create a late
_inlineBannerAd
variable to hold the reference to the banner ad we are going to create. Lastly, just like we did for the other banner ad, we need to be able to check if the ad is loaded before displaying it. For that we are going to add a _isInlineBannerAdLoaded
variable and set it to false
.
home_page.dart
class _HomePageState extends State<HomePage> {
final _inlineAdIndex = 3;
...
late BannerAd _inlineBannerAd;
...
bool _isInlineBannerAdLoaded = false;
...
Next, we are going to create a function which is almost identical to the one we created earlier that will take care of creating a BannerAd
and loading it.
home_page.dart
void _createInlineBannerAd() {
_inlineBannerAd = BannerAd(
size: AdSize.mediumRectangle,
adUnitId: AdHelper.bannerAdUnitId,
request: AdRequest(),
listener: BannerAdListener(
onAdLoaded: (_) {
setState(() {
_isInlineBannerAdLoaded = true;
});
},
onAdFailedToLoad: (ad, error) {
ad.dispose();
},
),
);
_inlineBannerAd.load();
}
There are a few things we need to note here. First, you’ll notice we are using a different size for this ad. AdSize.mediumRectangle
will display an ad that's 320X250dp. Because of the rectangular appearance of our news tiles, this just seems more fitting here.
Here we're also using the AdHelper
class to retrieve the same bannerAdUnitId
we used for the previous ad. While this is convenient in our little demo, this isn’t the best practice in production. What you should be doing instead is creating separate ad units for every placement or activity in your app. This will allow you to track the performance of individual ad units.
Everything else in this function is pretty much the same as in the one we created for our bottom banner ad.
Just like before, we need to call the _createInlineBannerAd
function from inside of initState
and call dispose
from the dispose
method.
home_page.dart
@override
void initState() {
super.initState();
...
_createInlineBannerAd();
}
@override
void dispose() {
super.dispose();
...
_inlineBannerAd.dispose();
}
Adding the Inline Banner Ad to the Widget Tree
The last thing left to do is to display the banner ad we just created within our ListView
. We only want to display this ad if it has loaded, so we need to establish the appropriate checks for this. First, let’s change the itemCount
in the ListView.builder
to account for our ad.
home_page.dart
...
body: ListView.builder(
padding: const EdgeInsets.all(10),
itemCount:
NewsArticle.articles.length + (_isInlineBannerAdLoaded ? 1 : 0),
...
Here we are saying that the itemCount
should be equal to the length of the List
of articles if the ad isn't loaded. If it is loaded then, we want to add one to that length value. This makes sense because displaying the ad would increase the number of items we have in the ListView
by one.
Now, let’s move on to the itemBuilder
argument. Here we want to display an AdWidget
using _inlineBannerAd
if two conditions are met. We want to display the AdWidget
if the ad is loaded and if the current index is equal to the index where we want the ad positioned. Earlier, we defined that index under the _inlineAdIndex
variable as 3. Also, just like for the bottom banner ad, we'll wrap this AdWidget
in a Container
and give it a height and width obtained using _inlineBannerAd.size
.
home_page.dart
...
itemBuilder: (context, index) {
if (_isInlineBannerAdLoaded && index == _inlineAdIndex) {
return Container(
padding: EdgeInsets.only(
bottom: 10,
),
width: _inlineBannerAd.size.width.toDouble(),
height: _inlineBannerAd.size.height.toDouble(),
child: AdWidget(ad: _inlineBannerAd),
);
} else {
final article = NewsArticle.articles[index];
return Padding(
padding: const EdgeInsets.only(
bottom: 10,
),
child: GestureDetector(
onTap: () {
_showInterstitialAd();
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => NewsArticlePage(
title: article.headline,
imagePath: article.asset,
),
),
);
},
child: ArticleTile(
article: article,
),
),
);
}
So, now we’ve got the return statement for the Container
with the AdWidget
inside of an if
block. The remainder of the itemBuilder
function logic is inside of an else
block.
We're almost done here, but there's one last thing left to do. If you take a look at the else
block, you’ll see that we are getting individual NewsArticle
objects from the list of articles. We're then storing them inside of the article
variable. To do this we are using the current index
provided to us by the itemBuilder
function. The only problem here is that when we add the banner ad to the ListView
we are increasing the itemCount
. That means that the index
we receive is based on that itemCount
. The way our code is currently structured when we get the third NewsArticle
object, its index is two. The next index is three, and that is the index at which we display our ad. In the eyes of the itemBuilder
, the index after the ad is four. So, now if we try to get the next NewsArticle
object after the ad, we will get back the fifth NewsArticle
. The one we want to get is the fourth, not the fifth. To overcome this issue, we are going to create a helpful little function.
home_page.dart
int _getListViewItemIndex(int index) {
if (index >= _inlineAdIndex && _isInlineBannerAdLoaded) {
return index - 1;
}
return index;
}
This function takes in an index
which will be provided by the itemBuilder
. Then the function checks to see if the index
it received is equal to or greater than the _inlineAdIndex
. In the same if
statement condition it will check if the inline banner ad is loaded. If this condition returns true
, we'll decrement the index
by one and return that. Otherwise, if the condition returns false
, we'll simply return the unmodified index
. Now, let’s replace the index
in NewsArticle.articles[index]
with this function call.
home_page.dart
...
else {
final article = NewsArticle.articles[_getListViewItemIndex(index)];
...
This takes care of the issue beautifully! Now, this function will just return the unmodified index
for any NewsArticle
objects displayed before the ad and also in the case that the ad isn’t loaded. Otherwise, it will return the decremented index
which will get us the NewsArticle
object we need.
Let’s save our work and restart the app. Now, scroll down past the third article tile and you should see the inline ad.
Displaying an Interstitial Ad
Since we can almost call ourselves experts at displaying banner ads, let’s take things up a notch. The final ad we are going to implement will be an interstitial ad. Inside an app, interstitial ads are displayed as a full-screen overlay.
In our implementation we want to display this ad when a user taps to open one of the articles. We'll use a test ad unit ID provided by Google that's set up to display a video interstitial ad. Before the user gets to see the article, they must wait 5 seconds before they can dismiss this interstitial video ad. When the ad is dismissed, they will see the article.
Implementing interstitial ads is a bit different from banner ads. Once we break it down, though, you'll see how simple it really is.
Loading and Creating an Interstitial Ad
The thing about interstitial ads is that any given ad you load can only be displayed once. That’s why things will look a little bit different here compared to what you’re used to by now. It will all make more and more sense as we go through this section. First, we need to add a variable to _HomePageState
that will hold the reference to our ad. This will be a nullable variable.
home_page.dart
InterstitialAd? _interstitialAd;
Next, we need to create a function that will load the ad and initialize our _interstitialAd
variable.
home_page.dart
void _createInterstitialAd() {
InterstitialAd.load(
adUnitId: AdHelper.interstitialAdUnitId,
request: AdRequest(),
adLoadCallback: InterstitialAdLoadCallback(
onAdLoaded: (InterstitialAd ad) {
_interstitialAd = ad;
},
onAdFailedToLoad: (LoadAdError error) {
_interstitialAd = null;
_createInterstitialAd();
},
),
);
}
Looking at this code snippet, you may have already noticed some differences. One change is that instead of creating an InterstitialAd
object we are calling the InterstitialAd.load
method.
Some things still look familiar, though. We are providing the ad unit ID for our interstitial ad as an adUnitId
argument. Then, we are passing in an AdRequest
object to request the ad.
Lastly, we are using InterstitialAdLoadCallback
to perform certain actions when an ad loads or fails to load.
When the ad loads, the function callback gets access to an InterstitialAd
object. So here we are initializing the _interstitialAd
variable we created earlier with the InterstitialAd
object we get through this callback. In the case that the ad fails to load, we must set the _interstitialAd
variable to null
.
We'll be calling this _createInterstitialAd
function every time we need to load a new ad. One case when we need to load a new ad, is every time we show an interstitial ad. That is because as we discussed earlier an interstitial ad can only be shows once.
So, why are we setting the _interstitialAd
variable to null
when an ad fails to load? Well, imagine a scenario where we just showed an interstitial ad and now we need to load another one. At that point, the _interstitialAd
variable still references the previous InterstitialAd
object. If our new ad loads and overrides the _interstitialAd
variable with a new InterstitialAd
object, there’s no issue, but what if that ad fails to load? If we don’t do anything about it, the variable will still reference that previous ad, which we already showed. That is an issue, because we never want to show the same interstitial ad more than once. Setting the _interstitialAd
variable to null
in the case that the ad fails to load will keep us safe from trying to display an ad we already showed. The one other thing we do in the case the ad fails to load is call the _createInterstitialAd
function once more to try loading another ad.
Ad Load Failure Optimization
The way we load a new ad, if an ad fails to load, could be optimized. The way we have the code set up now could become troublesome if something goes wrong and a failure keeps recurring indefinitely. If that happens, we'll never stop trying to load a new ad. So, what we want to do instead is set up some simple logic that will only allow a limited number of load retries.
First, let's add a const
to represent the maximum number of ad load attempts we want to make in case an ad fails to load. We'll add it above the HomePage
widget.
home_page.dart
const int maxFailedLoadAttempts = 3;
class HomePage extends StatefulWidget {
...
Then, we need to add a variable that will keep track of how many ad load attempts were made. Add this variable inside the _HomePageState
and initially set it to 0.
home_page.dart
class _HomePageState extends State<HomePage> {
...
int _interstitialLoadAttempts = 0;
...
To finish up this optimization let's make some changes to the listeners in the _createInterstitialAd
function.
home_page.dart
...
adLoadCallback: InterstitialAdLoadCallback(
onAdLoaded: (InterstitialAd ad) {
_interstitialAd = ad;
_interstitialLoadAttempts = 0;
},
onAdFailedToLoad: (LoadAdError error) {
_interstitialLoadAttempts += 1;
_interstitialAd = null;
if (_interstitialLoadAttempts <= maxFailedLoadAttempts) {
_createInterstitialAd();
}
},
),
...
Let's discuss what's happening here. Now, each time the ad fails to load, we increment the _interstitialLoadAttempts
variable by 1. Then, we check to see if the number of attempts we made is less than or equal to the maximum load attempts we want to make. If that's the case, we attempt to load another ad. If the _interstitialLoadAttempts
exceeds the maximum load attempts we want to make, then we won't try to load another ad. This will protect us from trying to load a new ad indefinitely in the case of an unresolvable failure.
One other thing we are doing here, is resetting the _interstitialLoadAttempts
variable back to 0 when an ad loads successfully.
Now, we need to call the _createInterstitialAd
function from within initState
. We do this even before showing the ad because we want the ad to load and be immediately available when it's triggered to be shown. We also want to call dispose
on the ad inside the dispose
method of _HomePageState
.
home_page.dart
@override
void initState() {
super.initState();
...
_createInterstitialAd();
}
@override
void dispose() {
super.dispose();
...
_interstitialAd?.dispose();
}
Displaying an Interstitial Ad
We are going to create another function for showing an interstitial ad . The code in this function will only run if the _interstitialAd
variable is not null
.
home_page.dart
void _showInterstitialAd() {
if (_interstitialAd != null) {
_interstitialAd!.fullScreenContentCallback = FullScreenContentCallback(
onAdDismissedFullScreenContent: (InterstitialAd ad) {
ad.dispose();
_createInterstitialAd();
},
onAdFailedToShowFullScreenContent: (InterstitialAd ad, AdError error) {
ad.dispose();
_createInterstitialAd();
},
);
_interstitialAd!.show();
}
}
Here we are setting _interstitialAd!.fullScreenContent
with a FullScreenContentCallback
object. Using this object, we can listen to the ad’s lifecycle events and perform certain actions when they occur. You have access to more lifecycle events than we are using here. For example you can listen for when an impression occurs on an ad.
In our case, we only care about the onAdDismissedFullScreenContent
and onAdFailedToShowFullScreenContent
events. The first event occurs when an ad is dismissed. The onAdFailedToShowFullScreenContent
event can occur in instances such as when you are trying to show an interstitial ad that has already been shown.
For both events we have access to the InterstitialAd
object. As best practice you should always call dispose
on the ad from both of these callbacks. That's exactly what we are doing here, using the InterstitialAd
object we get from the callbacks. We're also calling _createInterstitialAd
when either of these events occur. To reiterate, that is because an interstitial ad can only be shown once, so after we show an ad we need to generate a new one.
After setting up the callbacks we are calling the show
method on our ad. This will display our ad to the user.
Now, let’s go ahead and trigger the _showInterstitialAd
function from within our widget tree. Head over to the GestureDetector
widget within the itemBuilder
of the ListView.builder
. Add the call to the _showInterstitialAd
right before Navigator.push
.
home_page.dart
...
child: GestureDetector(
onTap: () {
_showInterstitialAd();
Navigator.push(
...
This will ensure that when a user taps on an article tile they'll see the ad and also be routed to the article page. After 5 seconds the user will see a button they can press to dismiss the ad. When the ad is dismissed, the user will be able to see the article page.
Save your work, restart the app and tap on one of the articles. You should now see an interstitial video ad appear.
Conclusion
Amazing, you made it! You should now be able to start monetizing your Flutter apps through Google AdMob. Remember though, knowing how to place ads in your code is just one piece of the puzzle. If you are planning to use ads as a way to generate income from your apps, do your research on how to do it for maximum success.
You want your ad placement to be strategic and effective. You also should never jeopardize the overall user experience and bombard your users with ads. Make sure to use the metrics Google provides you with to see how your ads are performing and make educated decisions based on that data. Thanks for reading and happy coding!
where is githup link?
Hi Mariam,
You can always find the GitHub links for the tutorials at the top of the written articles in the “Getting Started” section.
Here it is as well.
https://github.com/ResoCoder/flutter-admob-monetization-banner-and-interstitial-ads-tutorial/
Hi Ashley,
I know this question is unrelated but i’d like to know if getx is more advisable to use for state management
Hi Joshua,
State management is a highly debated topic. For Flutter there are many options out there to choose from, so it can get overwhelming and confusing when trying to pick one. Getting familiar with several most popular options, such as Riverpod and Bloc/Cubit and then choosing whichever one you prefer and/or whichever one is most suitable for your particular project is likely the best way to go.
So what I would suggest to you is to try building a small practice project using different state management options and seeing which one you’re most comfortable with and learning their benefits/drawbacks for different use cases.
Hope this helps. 🙂
How can i implement a facebook bidding setup with admob?
Hi Ashley Novik
very helpful
thanks
Thanks, Ashley Novik. It was a great help for me. Thanks for the clear documentation and the tutorial video. Thanks again.
<3 thank you
Great job!
Worked at first try
your guide is excellent but I have a problem applying BannerAd to listview.separated. I have an error RangeError (index) Invalid Value> Not in inclusive range. Can you help me with this?
Thank you very much Ashley
Please how do I use persistentFooterButtons instead of bottomnavigationbar for the bannerad
The factory’s uPVC fittings are designed with meticulous attention to detail, ensuring secure and tight connections that minimize the risk of leaks or failures. Elitepipe Plastic Factory
Its like you read my mind! You appear to know so much about this, like you wrote the book in it or something. I think that you can do with a few pics to drive the message home a little bit, but instead of that, this is excellent blog. A fantastic read. I’ll certainly be back.
Usually I do not read article on blogs, however I would like to say that this write-up very compelled me to take a look at and do so! Your writing taste has been amazed me. Thanks, quite nice post.
Hey there, You have done a fantastic job. I will certainly digg it and personally recommend to my friends. I’m confident they’ll be benefited from this site.
What i don’t understood is in reality how you’re now not really a lot more smartly-favored than you might be now. You’re very intelligent. You understand therefore significantly in terms of this topic, produced me personally believe it from a lot of numerous angles. Its like women and men are not interested except it is one thing to accomplish with Woman gaga! Your own stuffs outstanding. Always care for it up!
What i do not realize is in fact how you are no longer actually much more well-favored than you might be right now. You’re very intelligent. You recognize thus considerably in relation to this topic, made me in my view believe it from numerous numerous angles. Its like men and women are not fascinated until it is one thing to do with Lady gaga! Your own stuffs excellent. All the time handle it up!
Simply wish to say your article is as amazing. The clearness in your post is just nice and i could assume you’re an expert on this subject. Well with your permission let me to grab your feed to keep updated with forthcoming post. Thanks a million and please carry on the gratifying work.
Thanks, I have recently been looking for info about this subject for a while and yours is the greatest I have discovered so far. However, what in regards to the bottom line? Are you certain in regards to the supply?
of course like your website but you have to check the spelling on several of your posts. A number of them are rife with spelling issues and I in finding it very troublesome to inform the reality on the other hand I will certainly come back again.
Thank you I have just been searching for information approximately this topic for a while and yours is the best I have found out so far However what in regards to the bottom line Are you certain concerning the supply
you are truly a just right webmaster The site loading speed is incredible It kind of feels that youre doing any distinctive trick In addition The contents are masterwork you have done a great activity in this matter
Ive read several just right stuff here Certainly price bookmarking for revisiting I wonder how a lot effort you place to create this kind of great informative website
Usually I do not read article on blogs however I would like to say that this writeup very compelled me to take a look at and do so Your writing taste has been amazed me Thanks quite nice post
Increase your earnings AffRip
Increase your earnings Top Affiliate Marketing
Monetize your website Top Affiliate Marketing
Monetize your web presence Affiliate Discord
Earn passive income AffRip
Stay up to date with technology Compiler
学习网上赚钱 联盟营销社区
Modern Talking был немецким дуэтом, сформированным в 1984 году. Он стал одним из самых ярких представителей евродиско и популярен благодаря своему неповторимому звучанию. Лучшие песни включают “You’re My Heart, You’re My Soul”, “Brother Louie”, “Cheri, Cheri Lady” и “Geronimo’s Cadillac”. Их музыка оставила неизгладимый след в истории поп-музыки, захватывая слушателей своими заразительными мелодиями и запоминающимися текстами. Modern Talking продолжает быть популярным и в наши дни, оставаясь одним из символов эпохи диско. Музыка 2024 года слушать онлайн и скачать бесплатно mp3.
Bwer Pipes: Your Key to Agricultural Success in Iraq: Count on Bwer Pipes to provide you with high-quality irrigation solutions designed to meet the demands of Iraqi farming. Our cutting-edge sprinkler systems and reliable pipes ensure precise water distribution, contributing to healthier crops and increased profitability. Visit Bwer Pipes
Thanks for sharing. I read many of your blog posts, cool, your blog is very good.
The level of my admiration for your work mirrors your own sentiment. The sketch is elegant, and the authored material is stylish. Nevertheless, you appear concerned about the prospect of embarking on something that may be seen as dubious. I agree that you’ll be able to address this issue promptly.
Somebody essentially lend a hand to make significantly posts I might state That is the very first time I frequented your web page and up to now I surprised with the research you made to create this particular put up amazing Excellent job
Your blog is a treasure trove of valuable insights and thought-provoking commentary. Your dedication to your craft is evident in every word you write. Keep up the fantastic work!
helloI really like your writing so a lot share we keep up a correspondence extra approximately your post on AOL I need an expert in this house to unravel my problem May be that is you Taking a look ahead to see you
Wow amazing blog layout How long have you been blogging for you made blogging look easy The overall look of your web site is magnificent as well as the content
Its like you read my mind You appear to know so much about this like you wrote the book in it or something I think that you can do with a few pics to drive the message home a little bit but other than that this is fantastic blog A great read Ill certainly be back
Hi i think that i saw you visited my web site thus i came to Return the favore I am attempting to find things to improve my web siteI suppose its ok to use some of your ideas
Temp mail very informative articles or reviews at this time.
Your blog is a shining example of excellence in content creation. I’m continually impressed by the depth of your knowledge and the clarity of your writing. Thank you for all that you do.
Belo blog aqui Além disso, seu site carrega muito rápido Qual host você está usando Posso obter seu link de afiliado para seu host? Desejo que meu site carregue tão rápido quanto o seu haha
Program iz Nice post. I learn something totally new and challenging on websites
Mygreat learning very informative articles or reviews at this time.
Simply desire to say your article is as surprising The clearness in your post is simply excellent and i could assume you are an expert on this subject Fine with your permission let me to grab your feed to keep up to date with forthcoming post Thanks a million and please carry on the gratifying work
Tech to Trick This is my first time pay a quick visit at here and i am really happy to read everthing at one place
allegheny county real estate I like the efforts you have put in this, regards for all the great content.
Hi i think that i saw you visited my web site thus i came to Return the favore I am attempting to find things to improve my web siteI suppose its ok to use some of your ideas
I have read some excellent stuff here Definitely value bookmarking for revisiting I wonder how much effort you put to make the sort of excellent informative website
Tech to Force For the reason that the admin of this site is working, no uncertainty very quickly it will be renowned, due to its quality contents.
obviously like your website but you need to test the spelling on quite a few of your posts Several of them are rife with spelling problems and I to find it very troublesome to inform the reality on the other hand Ill certainly come back again
Simply Sseven There is definately a lot to find out about this subject. I like all the points you made
Corrugated Metal Pipes in Iraq: At Elite Pipe Factory in Iraq, we also specialize in the production of Corrugated Metal Pipes, which are designed for strength and resilience in heavy-duty applications. Our corrugated metal pipes are constructed to handle high loads and resist environmental stresses, making them suitable for use in stormwater management, road construction, and culverts. With our commitment to quality and innovation, Elite Pipe Factory ensures that these pipes provide exceptional performance and durability. As one of the leading and most trusted factories in Iraq, we pride ourselves on offering products that exceed expectations. Learn more about our Corrugated Metal Pipes on our website elitepipeiraq.com.
Henof I like the efforts you have put in this, regards for all the great content.
SocialMediaGirls Very well presented. Every quote was awesome and thanks for sharing the content. Keep sharing and keep motivating others.
I am not sure where youre getting your info but good topic I needs to spend some time learning much more or understanding more Thanks for magnificent info I was looking for this information for my mission
Lois Sasson Hi there to all, for the reason that I am genuinely keen of reading this website’s post to be updated on a regular basis. It carries pleasant stuff.
I loved as much as you will receive carried out right here The sketch is attractive your authored material stylish nonetheless you command get got an impatience over that you wish be delivering the following unwell unquestionably come more formerly again since exactly the same nearly a lot often inside case you shield this hike
My brother suggested I might like this blog He was totally right This post actually made my day You can not imagine simply how much time I had spent for this info Thanks
Houzzmagazine naturally like your web site however you need to take a look at the spelling on several of your posts. A number of them are rife with spelling problems and I find it very bothersome to tell the truth on the other hand I will surely come again again.
great post for sharing
SOUNDOS-SEGC.
Baddiehub There is definately a lot to find out about this subject. I like all the points you made