Native ads integration for Flutter

Native ads are a form of advertising that you can customize to blend in with the other content in your app. This makes ads appear more organic, which leads to a better user experience and higher retention.

Before you start

Make sure you have correctly integrated the ironSource Flutter Plugin 7.9.0 (alpha) or 8.4.0+ (will be available in November 2024) into your application. The integration is outlined here

There are two ways to integrate LevelPlay native ads using the Flutter plugin:

  • Native Templates: These are predefined templates provided by the plugin in the form of XML and XIB files.
  • Custom Templates: These templates are styled and designed by developers.

Native Templates

Native templates are predefined views that implement the native ad logic. Using this setup is recommended for fast and easy implementation. It handles the population of views once the ad has loaded and clears them once the ad is destroyed.

There are two template options:

  • Small: Templates that do not include the media view.
  • Medium: Templates that feature the media view.

While the styling is generally similar, you can also customize it according to your preference.

Android iOS
Small
Medium

To integrate native templates, follow the steps below:

Step 1. Create LevelPlayNativeAd Object

Create a LevelPlayNativeAd object responsible for loading the ad into the LevelPlayNativeAdView container. This object will handle the ad methods such as load, destroy and will define the ad placement and listener for event callbacks.

_nativeAd = LevelPlayNativeAd.builder()
        .withPlacementName([YOUR_PLACEMENT])
        .withListener([YOUR_LEVEL_PLAY_NATIVE_AD_LISTENER])
        .build();

Step 2. Implement the Listener

Next, implement the LevelPlayNativeAdListener in your code. The LevelPlay SDK fires several callbacks to inform you of native ad activity. The SDK will notify your Listener of all the events listed below:

/**
 Called after a native ad has been clicked.
 @param nativeAd Level Play native ad.
 @param adInfo The info of the ad.
 */ 
@override
void onAdClicked(LevelPlayNativeAd? nativeAd, IronSourceAdInfo? adInfo) {}
/**
 Called after a native ad impression has been recorded.
 @param nativeAd Level Play native ad.
 @param adInfo The info of the ad.
 */
 @override
 void onAdImpression(LevelPlayNativeAd? nativeAd, IronSourceAdInfo? adInfo) {}
/**
 Called after a native has attempted to load an ad but failed.
 @param nativeAd Level Play native ad.
 @param error The reason for the error
 */  
@override
void onAdLoadFailed(LevelPlayNativeAd? nativeAd, IronSourceError? error) {}
/**
 Called after a native ad has been successfully loaded
 @param nativeAd Level Play native ad.
 @param adInfo The info of the ad.
 */
@override
void onAdLoaded(LevelPlayNativeAd? nativeAd, IronSourceAdInfo? adInfo) {}

Step 3. Create LevelPlayNativeAdView

Create a LevelPlayNativeAdView widget to define the container that will host the loaded native ad. This object will define the native ad boundaries by determining width and height or setting box constraints for the container. It can also handle the native ad elements styling, such as: title, body, advertiser and call to action button.

Note: For native templates the default type is SMALL and can be altered by defining the template type on the widget creation. 

LevelPlayNativeAdView(
          height: 350, // Recommeneded height for Medium Type
          width: 300, // Recommeneded width for Medium Type
          nativeAd: _nativeAd,
          onPlatformViewCreated: () {
            _nativeAd?.loadAd(); // Recommeneded place to loadAd
          },
          templateType: LevelPlayTemplateType.MEDIUM,
          templateStyle: [LevelPlayNativeAdTemplateStyle] optional
)
LevelPlayNativeAdView(
          height: 175, // Recommeneded height for Small Type
          width: 300, // Recommeneded width for Small Type
          nativeAd: _nativeAd,
          onPlatformViewCreated: () {
            _nativeAd?.loadAd(); // Recommeneded place to loadAd
          },
          templateType: LevelPlayTemplateType.SMALL,
          templateStyle: [LevelPlayNativeAdTemplateStyle] optional
)

Step 3. Load the ad

Call loadAd to load a native ad. This can be called after receiving onPlatformViewCreated callback of the native ad view container or in another timing decided by the developer.

_nativeAd?.loadAd();

Step 4. Destroy the Native Ad

To destroy a native ad, call the following method:

  _nativeAd?.destroyAd();

A destroyed native ad can no longer be loaded. If you want to serve it again, you must recreate the ad container widget.

Custom Templates

Custom templates allow you to design your own styles and features to fit your specific needs. They provide flexibility to personalize layouts and functionalities, ensuring a unique user experience.

These templates are mainly used when a higher level of control over the ad design is desired. It can be implemented for both Android and iOS platforms and require additional code implementation.

To create custom templates, you’ll need to write native code and develop your own custom layouts. Follow the steps below for integration:

Step 1. Create NativeAdViewFactory

The Android or iOS implementation of the class extending LevelPlayNativeAdViewFactory will display the loaded ad using your customized layout.

Android

// Android Implementation 
import com.ironSource.ironsource_mediation.LevelPlayNativeAdViewFactory
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import com.ironsource.mediationsdk.ads.nativead.LevelPlayMediaView
import com.ironsource.mediationsdk.ads.nativead.LevelPlayNativeAd
import com.ironsource.mediationsdk.ads.nativead.NativeAdLayout
import io.flutter.plugin.common.BinaryMessenger
/**
 * This class is an example of how to implement custom native ad.
 * The Class must receive BinaryMessenger and the layoutId of the
 * native ad layout that the developer wants to load. It also
 * must extend the LevelPlayNativeAdViewFactory and override the
 * method bindNativeAdToView in order to fill the view with the
 * loaded native ad.
 */
class NativeAdViewFactoryExample(
    levelPlayBinaryMessenger: BinaryMessenger,
    layoutId: Int
) : LevelPlayNativeAdViewFactory(levelPlayBinaryMessenger, layoutId) {
    override fun bindNativeAdToView(nativeAd: LevelPlayNativeAd?, nativeAdLayout: NativeAdLayout) {
        // Extract views
        val titleView = nativeAdLayout.findViewById<TextView>(R.id.adTitle)
        val bodyView = nativeAdLayout.findViewById<TextView>(R.id.adBody)
        val advertiserView = nativeAdLayout.findViewById<TextView>(R.id.adAdvertiser)
        val callToActionView = nativeAdLayout.findViewById<Button>(R.id.adCallToAction)
        val iconView = nativeAdLayout.findViewById<ImageView>(R.id.adAppIcon)
        val mediaView = nativeAdLayout.findViewById<LevelPlayMediaView>(R.id.adMedia)
        // Bind native ad to view
        if (nativeAd != null) {
            if (nativeAd.title != null) {
                titleView.text = nativeAd.title
                nativeAdLayout.setTitleView(titleView)
            }
            if (nativeAd.body != null) {
                bodyView.text = nativeAd.body
                nativeAdLayout.setBodyView(bodyView)
            }
            if (nativeAd.advertiser != null) {
                advertiserView.text = nativeAd.advertiser
                nativeAdLayout.setAdvertiserView(advertiserView)
            }
            if (nativeAd.callToAction != null) {
                callToActionView.text = nativeAd.callToAction
                nativeAdLayout.setCallToActionView(callToActionView)
            }
            if (nativeAd.icon != null) {
                iconView!!.setImageDrawable(nativeAd.icon!!.drawable)
                nativeAdLayout.setIconView(iconView)
            }
            if (mediaView != null) {
                nativeAdLayout.setMediaView(mediaView)
            }
            nativeAdLayout.registerNativeAdViews(nativeAd)
        }
    }
}

iOS

// iOS Implementation
/// h file
#import <Foundation/Foundation.h>
#import <Flutter/Flutter.h>
#import <IronSource/IronSource.h>
#import "LevelPlayNativeAdViewFactory.h"
/**
 * This class is an example of how to implement custom native ad.
 * The Class must receive BinaryMessenger and the layoutId of the
 * native ad layout that the developer wants to load. It also
 * must extend the LevelPlayNativeAdViewFactory and override the
 * method bindNativeAdToView in order to fill the view with the
 * loaded native ad.
 */
@interface NativeAdViewFactoryExample : LevelPlayNativeAdViewFactory <LevelPlayNativeAdViewFactoryDelegate>
- (instancetype)initWithMessenger:(id<FlutterBinaryMessenger>)levelPlayBinaryMessenger layoutName:(nullable NSString *)layoutName;
@end
/// m file
#import "NativeAdViewFactoryExample.h"
@implementation NativeAdViewFactoryExample
- (instancetype)initWithMessenger:(id<FlutterBinaryMessenger>)levelPlayBinaryMessenger layoutName:(nullable NSString *)layoutName {
    self = [super initWithMessenger:levelPlayBinaryMessenger delegate:self layoutName:layoutName];
    return self;
}
- (void)bindNativeAdToView:(LevelPlayNativeAd *)nativeAd isNativeAdView:(ISNativeAdView *)isNativeAdView {
    // Extract views
    UILabel *titleView = isNativeAdView.adTitleView;
    UILabel *bodyView = isNativeAdView.adBodyView;
    UILabel *advertiserView = isNativeAdView.adBodyView;
    UIButton *callToActionView = isNativeAdView.adCallToActionView;
    UIImageView *iconView = isNativeAdView.adAppIcon;
    LevelPlayMediaView *mediaView = isNativeAdView.adMediaView;
    // Bind native ad to view
    if (nativeAd != nil) {
        if (nativeAd.title != nil) {
            titleView.text = nativeAd.title;
            [isNativeAdView setAdTitleView:titleView];
        }
        if (nativeAd.body != nil) {
            bodyView.text = nativeAd.body;
            [isNativeAdView setAdBodyView:bodyView];
        }
        if (nativeAd.advertiser != nil) {
            advertiserView.text = nativeAd.advertiser;
            [isNativeAdView setAdAdvertiserView:advertiserView];
        }
        if (nativeAd.callToAction != nil) {
            [callToActionView setTitle:nativeAd.callToAction forState:UIControlStateNormal];
            [isNativeAdView setAdCallToActionView:callToActionView];
        }
        if (nativeAd.icon != nil) {
            iconView.image = nativeAd.icon.image;
            [isNativeAdView setAdAppIcon:iconView];
        }
        if (mediaView != nil) {
            [isNativeAdView setAdMediaView:mediaView];
        }
        // Register native ad views with the provided native ad
        [isNativeAdView registerNativeAdViews:nativeAd];
    }
}
@end

Step 2. Register your NativeAdViewFactory

Next, register your class the in MainActivity or AppDelegate.

Note: Your unique view type string needs to correspond with the viewType you’ve set in the LevelPlayNativeAdView widget on the Flutter side.

Android

 // Android Implementation 
import com.ironSource.ironsource_mediation.IronSourceMediationPlugin
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        // Custom native ad view template must be registered here
        IronSourceMediationPlugin.registerNativeAdViewFactory(flutterEngine, [YOUR_UNIQUE_VIEW_TYPE], NativeAdViewFactoryExample(flutterEngine.dartExecutor.binaryMessenger, R.layout.my_custom_native_ad_view)) // your xml id
    }
    override fun cleanUpFlutterEngine(flutterEngine: FlutterEngine) {
        super.cleanUpFlutterEngine(flutterEngine)
        // Custom native ad view template must be unregistered here
        IronSourceMediationPlugin.unregisterNativeAdViewFactory(flutterEngine, viewType)
    }
}

To see an example on the Android NativeAdView layout, refer to my_custom_native_ad_view_template.xml.

iOS

 // iOS Implementation 
#import "AppDelegate.h"
#import "GeneratedPluginRegistrant.h"
#import "NativeAdViewFactoryExample.h"
#import "IronSourceMediationPlugin.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
  UIViewController *rootViewController = self.window.rootViewController;
  // Check if the root view controller is a FlutterViewController
  if ([rootViewController isKindOfClass:[FlutterViewController class]]) {
    // Cast the root view controller to FlutterViewController
    FlutterViewController *flutterViewController = (FlutterViewController *)rootViewController;
    NativeAdViewFactoryExample *nativeAdViewFactoryExample = [[NativeAdViewFactoryExample alloc] initWithMessenger: flutterViewController.binaryMessenger layoutName: @"MyCustomNativeAdViewTemplate"]; // your xib name
    // Custom native ad view template must be registered here
    [IronSourceMediationPlugin registerNativeAdViewFactory:self
                                                  viewTypeId:[YOUR_UNIQUE_VIEW_TYPE]
                                         nativeAdViewFactory:nativeAdViewFactoryExample];
  }
  // Override point for customization after application launch.
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end

To see an example on the iOS NativeAdView layout, refer to MyCustomNativeAdViewTemplate.xib

Step 3. Create LevelPlayNativeAdView

Create a LevelPlayNativeAdView widget to define the container that will host the loaded native ad. This object will define the native ad boundaries by determining width and height or setting box constraints for the container. It can also handle the native ad elements styling, such as: title, body, advertiser and call to action button.

Note: When creating custom templates, ensure the viewType aligns with the unique view type specified in the native Android or iOS sections. There’s no need for a template type definition, as you’re free to style your view according to your preferences.

LevelPlayNativeAdView(
          height: [HEIGHT], // Your recommeneded height
          width:[WIDTH], // Your recommeneded width
          nativeAd: _nativeAd,
          onPlatformViewCreated: () {
            _nativeAd?.loadAd(); // Recommeneded place to loadAd
          },
          viewType: [YOUR_UNIQUE_VIEW_TYPE]
)

Step 4. Load the ad

Call loadAd to load a native ad. This method can be called on onPlatformViewCreated callback of the native ad view container or in another timing decided by the developer.

_nativeAd?.loadAd();

Step 5. Destroy the Native Ad

To destroy a native ad, invoke the destroyAd method:

_nativeAd?.destroyAd();

A destroyed native ad can no longer be loaded. If you want to serve it again, you must recreate the ad container widget.

Done!
You can now deliver Native Ads through LevelPlay.