Skip to main content

Native Ad Format

  • Unlike other ad formats where the mediation SDK implements the ad view, native ads provide ad components for you to build the ad view directly.
  • The key advantage is minimizing disruption by implementing layouts based on your UI/UX. However, you must include ad markers to prevent users from confusing ads with content.
Native Example Elements En Pn
4 Required Native Ad ElementsNative ads can be freely designed to match your app’s UI, but the following 4 elements are mandatory:
  1. Ad Label: Add “AD” or similar text so users clearly recognize it as an advertisement.
  2. AdChoices Icon: Automatically inserted by the DARO SDK. Ensure it’s not obscured by other UI elements.
  3. Ad Title: Display the ad’s headline.
  4. CTA (Call to Action): Include a CTA button such as “Install”, “Open”, “Download”. The size and format are flexible.

Registering Native Factory

To use native ads in Flutter, you must register a native ad factory on the native platform (iOS/Android). The factoryId is the identifier of the factory registered on the native platform.
1

Create Ad Layout XML

Create a native ad layout file in android/app/src/main/res/layout/.
sample_native_ad.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="400dp">

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:cardCornerRadius="12dp"
        app:cardElevation="4dp"
        app:cardBackgroundColor="#1E1E1E">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:padding="12dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:paddingBottom="12dp">

                <ImageView
                    android:id="@+id/ad_app_icon"
                    android:layout_width="56dp"
                    android:layout_height="56dp"
                    android:scaleType="centerCrop" />

                <LinearLayout
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:layout_marginStart="12dp"
                    android:orientation="vertical">

                    <TextView
                        android:id="@+id/ad_headline"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:textSize="16sp"
                        android:textStyle="bold"
                        android:maxLines="2"
                        android:ellipsize="end" />

                    <TextView
                        android:id="@+id/ad_advertiser"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:textSize="13sp"
                        android:layout_marginTop="4dp" />
                </LinearLayout>
            </LinearLayout>

            <FrameLayout
                android:id="@+id/ad_media"
                android:layout_width="match_parent"
                android:layout_height="180dp" />

            <TextView
                android:id="@+id/ad_body"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="12dp"
                android:textSize="14sp"
                android:maxLines="2"
                android:ellipsize="end" />

            <Button
                android:id="@+id/ad_call_to_action"
                android:layout_width="match_parent"
                android:layout_height="44dp"
                android:layout_marginTop="12dp"
                android:textSize="16sp"
                android:textStyle="bold" />
        </LinearLayout>
    </androidx.cardview.widget.CardView>
</FrameLayout>
2

Implement DaroNativeAdFactory

Create a class that implements the DaroNativeAdFactory interface.
SampleNativeAdFactory.kt
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import so.daro.flutter.native.DaroNativeAdFactory
import droom.daro.core.model.DaroNativeAdBinder

class SampleNativeAdFactory(private val context: Context) : DaroNativeAdFactory {

    override fun createNativeAdView(): View {
        return LayoutInflater.from(context).inflate(R.layout.sample_native_ad, null)
    }

    override fun createAdBinder(view: View): DaroNativeAdBinder {
        return DaroNativeAdBinder.Builder(view)
            .setTitleViewId(R.id.ad_headline)
            .setBodyTextViewId(R.id.ad_body)
            .setIconViewId(R.id.ad_app_icon)
            .setMediaViewGroupId(R.id.ad_media)
            .setCallToActionViewId(R.id.ad_call_to_action)
            .build()
    }
}
3

Register Factory in MainActivity

Register the factory in configureFlutterEngine of your MainActivity.
MainActivity.kt
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import so.daro.flutter.DaroFlutterPlugin

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        DaroFlutterPlugin.registerNativeAdFactory(
            SampleNativeAdFactory(this),
            "sample_native_ad"
        )
    }
}
The factoryId passed to DaroNativeAd must exactly match the factory ID registered on the native platform.

Implementing Native Ads

Native ads follow a Create Ad object → Load → Display widget → Dispose pattern.
import 'package:daro_flutter/daro_flutter.dart';

1. Create Ad Object

Create a DaroNativeAd object and configure callbacks.
final nativeAd = DaroNativeAd(
  adUnitId: '{YOUR_AD_UNIT_ID}',
  factoryId: '{YOUR_FACTORY_ID}',
  onAdLoaded: (adInfo) {
    print('Native ad loaded: ${adInfo.adUnitId}');
    setState(() {
      _isAdLoaded = true;
    });
  },
  onAdFailedToLoad: (error) {
    print('Native ad failed to load: ${error.message}');
    nativeAd.dispose();
  },
  onAdClicked: (adInfo) {
    print('Native ad clicked');
  },
  onAdImpression: (adInfo) {
    print('Native ad impression');
  },
);

2. Load the Ad

nativeAd.load();

3. Display the Widget

After the onAdLoaded callback fires, place the DaroNativeAdWidget in the widget tree.
@override
Widget build(BuildContext context) {
  return Column(
    children: [
      // ... other widgets
      if (_isAdLoaded)
        DaroNativeAdWidget(ad: nativeAd),
    ],
  );
}
Placing DaroNativeAdWidget in the widget tree before calling ad.load() will throw a FlutterError. Always mount the widget after the onAdLoaded callback.

4. Dispose Resources

Call dispose() to clean up resources when leaving the page or when the ad is no longer needed.
@override
void dispose() {
  nativeAd.dispose();
  super.dispose();
}

Callback Reference

CallbackDescription
onAdLoadedCalled when the ad is successfully loaded
onAdFailedToLoadCalled when ad loading fails
onAdClickedCalled when the user clicks the ad
onAdImpressionCalled when an ad impression is recorded

LINE Native Ads

  • LINE native ads are compact native ad formats designed to be naturally inserted into feeds or lists.
  • They are more compact than standard native ads, ideal for embedding between list items.
  • The ad height is fixed at 36dp (Android) / 36pt (iOS).
  • Styles can be customized to match your app’s UI.
LINE Native Ad Example

Implementing LINE Native Ads

LINE native ads follow the same Create Ad object → Load → Display widget → Dispose pattern.

1. Create Ad Object

final lineNativeAd = DaroLineNativeAd(
  adUnitId: '{YOUR_AD_UNIT_ID}',
  onAdLoaded: (adInfo) {
    print('Line native ad loaded: ${adInfo.adUnitId}');
    setState(() {
      _isAdLoaded = true;
    });
  },
  onAdFailedToLoad: (error) {
    print('Line native ad failed to load: ${error.message}');
    lineNativeAd.dispose();
  },
  onAdClicked: (adInfo) {
    print('Line native ad clicked');
  },
  onAdImpression: (adInfo) {
    print('Line native ad impression');
  },
);

2. Load the Ad

lineNativeAd.load();

3. Display the Widget

if (_isAdLoaded)
  DaroLineNativeAdWidget(ad: lineNativeAd),
Placing DaroLineNativeAdWidget in the widget tree before calling ad.load() will throw a FlutterError. Always mount the widget after the onAdLoaded callback.

4. Dispose Resources

@override
void dispose() {
  lineNativeAd.dispose();
  super.dispose();
}

Callback Reference

CallbackDescription
onAdLoadedCalled when the ad is successfully loaded
onAdFailedToLoadCalled when ad loading fails
onAdClickedCalled when the user clicks the ad
onAdImpressionCalled when an ad impression is recorded

Style Customization

Use DaroLineNativeAdStyle to customize LINE native ad colors. Pass the style when creating the DaroLineNativeAd object.
final lineNativeAd = DaroLineNativeAd(
  adUnitId: '{YOUR_AD_UNIT_ID}',
  style: DaroLineNativeAdStyle(
    backgroundColor: Colors.white,
    contentColor: Colors.black,
    adMarkLabelTextColor: Colors.white,
    adMarkLabelBackgroundColor: Colors.grey,
  ),
  onAdLoaded: (adInfo) {
    print('Line native ad loaded');
    setState(() {
      _isAdLoaded = true;
    });
  },
  onAdFailedToLoad: (error) {
    print('Line native ad failed: ${error.message}');
    lineNativeAd.dispose();
  },
);

Style Properties

PropertyTypeDescription
backgroundColorColor?Overall ad background color
contentColorColor?Ad content text color
adMarkLabelTextColorColor?Ad mark label text color
adMarkLabelBackgroundColorColor?Ad mark label background color