Native ads are ad assets that are presented to users via UI components that are native to the platform. They're shown using the same types of views with which you're already building your layouts, and can be formatted to match the visual design of the user experience in which they live. In coding terms, this means that when a native ad loads, your app receives a NativeAd object that contains its assets, and the app (rather than the Google Mobile Ads SDK) is then responsible for displaying them.
Broadly speaking, there are two parts to successfully implementing native ads: loading an ad via the SDK and displaying the ad content in your app. This guide is concerned with using the SDK to load native ads.
Platform setup
Native ads are presented to users through UI components that are native to the
platform (for example, a
View
on Android or a
UIView
on
iOS).
Since native ads require UI components native to a platform, this feature requires additional setup for Android and iOS:
Android
The Android implementation of the Google Mobile Ads plugin requires a class
that implements a NativeAdFactory
. In order to reference this API
from your Android project, add the following lines to your
settings.gradle
:
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() def plugins = new Properties() def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') if (pluginsFile.exists()) { pluginsFile.withInputStream { stream -> plugins.load(stream) } } plugins.each { name, path -> def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() include ":$name" project(":$name").projectDir = pluginDirectory }
A NativeAdFactory
contains a method that takes a
NativeAd
and custom options, and returns a
NativeAdView
. The
NativeAdView
is what is displayed in your app.
You can implement this in your MainActivity.java
or create a
separate class in the same directory as MainActivity.java
:
package my.app.path; import com.google.android.gms.ads.nativead.NativeAd; import com.google.android.gms.ads.nativead.NativeAdView; import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin.NativeAdFactory; import java.util.Map; class NativeAdFactoryExample implements NativeAdFactory { @Override public NativeAdView createNativeAd( NativeAd nativeAd, Map<String, Object> customOptions) { // Create NativeAdView } }
Each NativeAdFactory
needs to be registered with a
factoryId
a unique String
identifier, in
MainActivity.configureFlutterEngine(FlutterEngine)
A
NativeAdFactory
can be implemented and registered for each unique
native ad layout used by your app, or a single one can handle all layouts.
The NativeAdFactory
should also be unregistered in
cleanUpFlutterEngine(engine)
When building with
add-to-app.
MainActivity.java
should look similar to:
package my.app.path; import io.flutter.embedding.android.FlutterActivity; import io.flutter.embedding.engine.FlutterEngine; import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin; public class MainActivity extends FlutterActivity { @Override public void configureFlutterEngine(FlutterEngine flutterEngine) { flutterEngine.getPlugins().add(new GoogleMobileAdsPlugin()); super.configureFlutterEngine(flutterEngine); GoogleMobileAdsPlugin.registerNativeAdFactory(flutterEngine, "adFactoryExample", NativeAdFactoryExample()); } @Override public void cleanUpFlutterEngine(FlutterEngine flutterEngine) { GoogleMobileAdsPlugin.unregisterNativeAdFactory(flutterEngine, "adFactoryExample"); } }
When creating the NativeAd
in Dart, the factoryId
needs to match the one used to add the factory to
GoogleMobileAdsPlugin
. In the above code snippet,
adFactoryExample
is the name of the factoryId
. Here is
a NativeAdFactory
example:
package io.flutter.plugins.googlemobileadsexample; import android.graphics.Color; import android.view.LayoutInflater; import android.widget.TextView; import com.google.android.gms.ads.nativead.NativeAd; import com.google.android.gms.ads.nativead.NativeAdView; import io.flutter.plugins.googlemobileads.GoogleMobileAdsPlugin.NativeAdFactory; import java.util.Map; /** * my_native_ad.xml can be found at * //github.com/googleads/googleads-mobile-flutter/tree/master/packages/google_mobile_ads/example/android/app/src/main/res/layout */ class NativeAdFactoryExample implements NativeAdFactory { private final LayoutInflater layoutInflater; NativeAdFactoryExample(LayoutInflater layoutInflater) { this.layoutInflater = layoutInflater; } @Override public NativeAdView createNativeAd( NativeAd nativeAd, Map<String, Object> customOptions) { final NativeAdView adView = (NativeAdView) layoutInflater.inflate(R.layout.my_native_ad, null); final TextView headlineView = adView.findViewById(R.id.ad_headline); final TextView bodyView = adView.findViewById(R.id.ad_body); headlineView.setText(nativeAd.getHeadline()); bodyView.setText(nativeAd.getBody()); adView.setBackgroundColor(Color.YELLOW); adView.setNativeAd(nativeAd); adView.setBodyView(bodyView); adView.setHeadlineView(headlineView); return adView; } }
iOS
The iOS implementation of the Google Mobile Ads plugin requires a class that
implements an FLTNativeAdFactory
. An
FLTNativeAdFactory
contains a method that takes a
GADNativeAd
and custom options and returns a
GADNativeAdView
. The GADNativeAdView
is
what is displayed in your app.
The FLTNativeAdFactory
protocol can be implemented by
AppDelegate
or a separate class could be created:
/* AppDelegate.m */ #import "FLTGoogleMobileAdsPlugin.h" @interface NativeAdFactoryExample : NSObject<FLTNativeAdFactory> @end @implementation NativeAdFactoryExample - (GADNativeAdView *)createNativeAd:(GADNativeAd *)nativeAd customOptions:(NSDictionary *)customOptions { // Create GADNativeAdView } @end
Each FLTNativeAdFactory
needs to be registered with a
factoryId
(a unique String
identifier) in
registerNativeAdFactory:factoryId:nativeAdFactory:
.
An FLTNativeAdFactory
can be implemented and registered for each
unique native ad layout used by your app, or a single one can handle all
layouts. This is done by importing FLTGoogleMobileAdsPlugin.h
and
calling registerNativeAdFactory:factoryId:nativeAdFactory:
with a
FlutterPluginRegistry
(a unique identifier for the factory) and the
factory itself. The factory must also be added after
GeneratedPluginRegistrant registerWithRegistry:self];
is
called.
If done in AppDelegate.m
, it should look similar to this:
#import "FLTGoogleMobileAdsPlugin.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [GeneratedPluginRegistrant registerWithRegistry:self]; NativeAdFactoryExample *nativeAdFactory = [[NativeAdFactoryExample alloc] init]; [FLTGoogleMobileAdsPlugin registerNativeAdFactory:self factoryId:@"adFactoryExample" nativeAdFactory:nativeAdFactory]; return [super application:application didFinishLaunchingWithOptions:launchOptions]; } @end
When creating the NativeAd
in Dart, the factoryID
needs to match the one used to add the factory to
FLTGoogleMobileAdsPlugin
. In the above code snippet,
adFactoryExample
is the name of the factoryID
. Here is
an example FLTNativeAdFactory
:
/** * The example NativeAdView.xib can be found at * //github.com/googleads/googleads-mobile-flutter/blob/master/packages/google_mobile_ads/example/ios/Runner/NativeAdView.xib */ @interface NativeAdFactoryExample : NSObject <FLTNativeAdFactory> @end @implementation NativeAdFactoryExample - (GADNativeAdView *)createNativeAd:(GADNativeAd *)nativeAd customOptions:(NSDictionary *)customOptions { // Create and place ad in view hierarchy. GADNativeAdView *adView = [[NSBundle mainBundle] loadNibNamed:@"NativeAdView" owner:nil options:nil].firstObject; // Associate the native ad view with the native ad object. This is // required to make the ad clickable. adView.nativeAd = nativeAd; // Populate the native ad view with the native ad assets. // The headline is guaranteed to be present in every native ad. ((UILabel *)adView.headlineView).text = nativeAd.headline; // These assets are not guaranteed to be present. Check that they are before // showing or hiding them. ((UILabel *)adView.bodyView).text = nativeAd.body; adView.bodyView.hidden = nativeAd.body ? NO : YES; [((UIButton *)adView.callToActionView) setTitle:nativeAd.callToAction forState:UIControlStateNormal]; adView.callToActionView.hidden = nativeAd.callToAction ? NO : YES; ((UIImageView *)adView.iconView).image = nativeAd.icon.image; adView.iconView.hidden = nativeAd.icon ? NO : YES; ((UILabel *)adView.storeView).text = nativeAd.store; adView.storeView.hidden = nativeAd.store ? NO : YES; ((UILabel *)adView.priceView).text = nativeAd.price; adView.priceView.hidden = nativeAd.price ? NO : YES; ((UILabel *)adView.advertiserView).text = nativeAd.advertiser; adView.advertiserView.hidden = nativeAd.advertiser ? NO : YES; // In order for the SDK to process touch events properly, user interaction // should be disabled. adView.callToActionView.userInteractionEnabled = NO; return adView; } @end
Always test with test ads
When building and testing your apps, make sure you use test ads rather than live, production ads. Failure to do so can lead to suspension of your account.
The easiest way to load test ads is to use our dedicated test ad unit ID for native ads:
The test ad units are configured to return test ads for every request, and you're free to use them in your own apps while coding, testing, and debugging. Just make sure you replace them with your own ad unit IDs before publishing your app.
Instantiate ad
A NativeAd
requires an adUnitId
, a factoryId
, an AdRequest
, and a
NativeAdListener
.The following example instantiates a native ad:
final NativeAd myNative = NativeAd(
adUnitId: '<ad unit id>',
factoryId: 'adFactoryExample',
request: AdRequest(),
listener: NativeAdListener(),
);
Factory ID
The factoryId
needs to match the one used to add the factory to
GoogleMobileAdsPlugin
on Android and/or the FLTGoogleMobileAdsPlugin
on iOS.
The same factoryId
can be used by both platforms, or each can have their own.
Native ad events
Through the use of NativeAdListener
, you can listen for lifecycle events, such
as when an ad is loaded. The following example implements each method and logs a
message to the console:
final NativeAdListener listener = NativeAdListener(
// Called when an ad is successfully received.
onAdLoaded: (Ad ad) => print('Ad loaded.'),
// Called when an ad request failed.
onAdFailedToLoad: (Ad ad, LoadAdError error) {
// Dispose the ad here to free resources.
ad.dispose();
print('Ad failed to load: $error');
},
// Called when an ad opens an overlay that covers the screen.
onAdOpened: (Ad ad) => print('Ad opened.'),
// Called when an ad removes an overlay that covers the screen.
onAdClosed: (Ad ad) => print('Ad closed.'),
// Called when an impression occurs on the ad.
onAdImpression: (Ad ad) => print('Ad impression.'),
// Called when a click is recorded for a NativeAd.
onNativeAdClicked: (NativeAd ad) => print('Ad clicked.'),
);
Load ad
After a NativeAd
is instantiated, load()
must be called before it can be
shown on the screen.
myNative.load();
Display ad
To display a NativeAd
as a widget, you must instantiate an AdWidget
with a
supported ad after calling load()
. You can create the widget before calling
load()
, but load()
must be called before adding it to the widget tree.
final AdWidget adWidget = AdWidget(ad: myBanner);
AdWidget
inherits from Flutter's Widget
class and can be used like any other
widget. On iOS, make sure you place the widget in a container with a specified
width and height. Otherwise, your Ad may not be displayed.
final Container adContainer = Container(
alignment: Alignment.center,
child: adWidget,
width: 500,
height: 500,
);
Once an Ad has called load()
, it must call dispose()
when access to it is no
longer needed. The best practice for when to call dispose()
is either after
the AdWidget
is removed from the widget tree or in the
AdListener.onAdFailedToLoad
callback.
That's it! Your app is now ready to display native ads.
Next steps
- Learn more about native ads in our native ad playbook.
- See native ads policies and guidelines for implementing native ads.
- Check out some customer success stories: Case study 1, Case Study 2.