Overview
Backfill ads automatically display alternative ads when direct ads are unavailable, maximizing revenue. Adrop supports major ad networks such as AdMob and Pangle as backfill ads.
Additional platform-specific setup is required to use backfill ads.
Android Setup
1. Gradle Configuration
settings.gradle.kts
Add the Pangle ad network repository:
dependencyResolutionManagement {
repositoriesMode. set (RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google ()
mavenCentral ()
maven { url = uri ( "https://artifact.bytedance.com/repository/pangle" ) }
}
}
build.gradle.kts
Add backfill ad dependencies:
build.gradle.kts (Module)
build.gradle (Module)
dependencies {
implementation ( "io.adrop:adrop-ads:1.7.2" )
implementation ( "io.adrop:adrop-ads-backfill:1.7.2" )
}
2. AndroidManifest.xml Configuration
If using AdMob as backfill ads, add the AdMob App ID to AndroidManifest.xml:
< manifest >
< application >
<!-- AdMob App ID -->
< meta-data
android:name = "com.google.android.gms.ads.APPLICATION_ID"
android:value = "ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy" />
</ application >
</ manifest >
Replace ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy with your actual AdMob App ID.
3. ProGuard Configuration
If using ProGuard, add the following rules:
-keep class io.adrop.** { *; }
-dontwarn io.adrop.**
iOS Setup
1. Modify Podfile
Add backfill ad dependencies to your Podfile:
target 'Runner' do
use_frameworks!
use_modular_headers!
# Adrop SDK
pod 'adrop-ads'
# Backfill Ads SDK
pod 'adrop-ads-backfill'
flutter_install_all_ios_pods File . dirname ( File . realpath ( __FILE__ ))
end
After adding dependencies, run the following command:
cd ios && pod install --repo-update && cd ..
2. Info.plist Configuration
If using AdMob as backfill ads, add the AdMob App ID to Info.plist:
< key > GADApplicationIdentifier </ key >
< string > ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy </ string >
Replace ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy with your actual AdMob App ID.
Console Configuration
Enable backfill ads in the Adrop Console:
Log in to AdControl Console
Navigate to Ad Units menu
Select the ad unit to use backfill ads
Enable backfill ads in the Backfill Settings section
Select the backfill ad network to use (AdMob, Pangle, etc.)
Enter ad network-specific settings (e.g., AdMob Ad Unit ID)
Using in Flutter
Checking Backfill Ads
Use the isBackfilled property to check if an ad is a backfill ad.
Native Ads
For native ads, you need to render the media view differently based on whether it’s a backfill ad.
import 'package:flutter/material.dart' ;
import 'package:adrop_ads_flutter/adrop_ads_flutter.dart' ;
import 'package:webview_flutter/webview_flutter.dart' ;
class NativeAdWithBackfill extends StatefulWidget {
const NativeAdWithBackfill ({ super .key});
@override
State < NativeAdWithBackfill > createState () => _NativeAdWithBackfillState ();
}
class _NativeAdWithBackfillState extends State < NativeAdWithBackfill > {
bool isLoaded = false ;
AdropNativeAd ? nativeAd;
late final WebViewController webViewController;
@override
void initState () {
super . initState ();
// Initialize WebView controller
webViewController = WebViewController ()
.. setJavaScriptMode ( JavaScriptMode .unrestricted);
_createNativeAd ();
}
void _createNativeAd () {
nativeAd = AdropNativeAd (
unitId : 'YOUR_UNIT_ID' ,
useCustomClick : true ,
listener : AdropNativeListener (
onAdReceived : (ad) {
debugPrint ( 'Ad received: ${ ad . isBackfilled ? "backfill" : "direct" } ' );
// Load HTML creative in WebView for direct ads
if ( ! ad.isBackfilled && ad.properties.creative != null ) {
webViewController. loadHtmlString (ad.properties.creative ! );
}
setState (() {
isLoaded = true ;
});
},
onAdFailedToReceive : (ad, errorCode) {
if (errorCode == AdropErrorCode .backfillNoFill) {
debugPrint ( 'No backfill ads available' );
} else {
debugPrint ( 'Ad failed to load: $ errorCode ' );
}
},
),
);
nativeAd ? . load ();
}
@override
Widget build ( BuildContext context) {
if ( ! isLoaded) return const SizedBox . shrink ();
return AdropNativeAdView (
ad : nativeAd,
child : Container (
padding : const EdgeInsets . all ( 16 ),
child : Column (
crossAxisAlignment : CrossAxisAlignment .start,
children : [
// Headline
if (nativeAd ? .properties.headline != null )
Text (
nativeAd ! .properties.headline ! ,
style : const TextStyle (
fontSize : 18 ,
fontWeight : FontWeight .bold,
),
),
const SizedBox (height : 8 ),
// Media view - render differently based on backfill status
_buildMediaView (),
// CTA button
if (nativeAd ? .properties.callToAction != null )
Padding (
padding : const EdgeInsets . only (top : 8 ),
child : ElevatedButton (
onPressed : () {},
child : Text (nativeAd ! .properties.callToAction ! ),
),
),
],
),
),
);
}
Widget _buildMediaView () {
if (nativeAd ? .isBackfilled == true ) {
// Backfill ad: use image asset
return Image . network (
nativeAd ? .properties.asset ?? '' ,
width : double .infinity,
height : 200 ,
fit : BoxFit .cover,
loadingBuilder : (context, child, loadingProgress) {
if (loadingProgress == null ) return child;
return const SizedBox (
height : 200 ,
child : Center (child : CircularProgressIndicator ()),
);
},
errorBuilder : (context, error, stackTrace) {
return const SizedBox (
height : 200 ,
child : Center (child : Icon ( Icons .error)),
);
},
);
} else if (nativeAd ? .properties.creative != null ) {
// Direct ad: render HTML creative with WebView
return SizedBox (
width : double .infinity,
height : 300 ,
child : WebViewWidget (controller : webViewController),
);
} else {
return const SizedBox . shrink ();
}
}
}
For native ads that are not backfill ads, video ads must be rendered directly using WebView.
Banner Ads
For banner ads, you can check backfill status through metadata.
bannerView = AdropBannerView (
unitId : 'YOUR_UNIT_ID' ,
listener : AdropBannerListener (
onAdReceived : (unitId, metadata) {
final isBackfilled = metadata ? [ 'isBackfilled' ] ?? false ;
if (isBackfilled == true ) {
debugPrint ( 'Backfill ad loaded' );
} else {
debugPrint ( 'Direct ad loaded' );
}
},
onAdFailedToReceive : (unitId, errorCode) {
if (errorCode == AdropErrorCode .backfillNoFill) {
debugPrint ( 'No backfill ads available' );
}
},
),
);
You can check backfill status similarly for interstitial, rewarded, and popup ads.
interstitialAd = AdropInterstitialAd (
unitId : 'YOUR_UNIT_ID' ,
listener : AdropInterstitialListener (
onAdReceived : (ad) {
debugPrint ( 'Ad loaded' );
// Interstitial ads don't have a separate isBackfilled property,
// but backfill ads are automatically loaded if backfill is configured in the console
},
onAdFailedToReceive : (ad, errorCode) {
if (errorCode == AdropErrorCode .backfillNoFill) {
debugPrint ( 'No direct or backfill ads available' );
}
},
),
);
Ad Serving Flow
Backfill ads are served in the following order:
Error Codes
Error codes related to backfill ads.
Error Code Description adNoFillCannot receive direct ads (will attempt backfill) backfillNoFillCannot receive backfill ads either
onAdFailedToReceive : (ad, errorCode) {
switch (errorCode) {
case AdropErrorCode .adNoFill :
debugPrint ( 'No direct ads. Attempting backfill.' );
break ;
case AdropErrorCode .backfillNoFill :
debugPrint ( 'No backfill ads available.' );
break ;
default :
debugPrint ( 'Ad load failed: ${ errorCode . code } ' );
}
}
Backfill ads support the following formats:
Ad Format Support Description Banner Supported Fixed-size banner ads Native Supported Customizable native ads Interstitial Supported Full-screen ads Rewarded Supported Rewarded ads Popup Supported Popup-style ads
Best Practices
Enable Backfill Ads Enable backfill ads for all ad units to maximize ad fill rate and revenue.
Set Appropriate Timeouts Set appropriate timeouts for direct and backfill ads to improve user experience.
Analyze Backfill Ads Track and analyze the ratio of direct to backfill ads using the isBackfilled property.
Handle Native Ad Media For native ads, use Image.network or WebView appropriately based on backfill status.
Important Notes
Android: You must add the io.adrop:adrop-ads-backfill:1.7.2 dependency to use backfill ads.
iOS: You must add pod 'adrop-ads-backfill' to your Podfile to use backfill ads.
When using AdMob, you must add the AdMob App ID to each platform’s manifest file.
For native ads that are not backfill ads, you must render media with WebView.
You must comply with the policies of backfill ad networks.
Next Steps