Skip to main content

Overview

Display backfill ads in WebView within your Flutter app by registering the WebView with the Adrop SDK using Adrop.registerWebView.

Prerequisites

Add the following packages to your project:
flutter pub add webview_flutter webview_flutter_android webview_flutter_wkwebview
WebView backfill ads require adrop-ads-backfill to be configured on both Android and iOS. See Getting Started for setup instructions.

Platform Configuration

Configure the native platforms to enable backfill ads in WebView.
Add the following to android/app/src/main/AndroidManifest.xml:
AndroidManifest.xml
<manifest>
    <application>
        <!-- WebView Backfill Ad Integration -->
        <meta-data
            android:name="com.google.android.gms.ads.INTEGRATION_MANAGER"
            android:value="webview"/>
    </application>
</manifest>
This configuration is required for backfill ads to work properly in WebView. Without it, backfill ads may not display.

Register WebView

Create a WebViewController, extract the platform-specific identifier, and register it with Adrop.registerWebView before loading content.
import 'dart:io';
import 'package:adrop_ads_flutter/adrop_ads_flutter.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:webview_flutter_android/webview_flutter_android.dart';
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';

class WebViewScreen extends StatefulWidget {
  const WebViewScreen({super.key});

  @override
  State<WebViewScreen> createState() => _WebViewScreenState();
}

class _WebViewScreenState extends State<WebViewScreen> {
  late final WebViewController _controller;
  bool _isReady = false;

  @override
  void initState() {
    super.initState();

    final PlatformWebViewControllerCreationParams params;
    if (WebViewPlatform.instance is WebKitWebViewPlatform) {
      params = WebKitWebViewControllerCreationParams(
        allowsInlineMediaPlayback: true,
        mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
      );
    } else {
      params = const PlatformWebViewControllerCreationParams();
    }

    _controller = WebViewController.fromPlatformCreationParams(params)
      ..setJavaScriptMode(JavaScriptMode.unrestricted);

    _registerAndLoad();
  }

  Future<void> _registerAndLoad() async {
    final int identifier;
    if (Platform.isAndroid) {
      identifier =
          (_controller.platform as AndroidWebViewController).webViewIdentifier;
    } else if (Platform.isIOS) {
      identifier =
          (_controller.platform as WebKitWebViewController).webViewIdentifier;
    } else {
      return;
    }

    await Adrop.registerWebView(identifier);

    setState(() => _isReady = true);
    _controller.loadRequest(Uri.parse('https://your-website.com'));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _isReady
          ? WebViewWidget(controller: _controller)
          : const Center(child: CircularProgressIndicator()),
    );
  }
}

Getting the WebView Identifier

The webViewIdentifier is extracted differently per platform:
PlatformControllerProperty
AndroidAndroidWebViewController.webViewIdentifier
iOSWebKitWebViewController.webViewIdentifier
if (Platform.isAndroid) {
  identifier =
      (_controller.platform as AndroidWebViewController).webViewIdentifier;
} else if (Platform.isIOS) {
  identifier =
      (_controller.platform as WebKitWebViewController).webViewIdentifier;
}
Call Adrop.registerWebView() before loading any web content. Load the URL only after registration is complete.

iOS WebView Configuration

For iOS, configure inline media playback using WebKitWebViewControllerCreationParams:
final params = WebKitWebViewControllerCreationParams(
  allowsInlineMediaPlayback: true,
  mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
);

_controller = WebViewController.fromPlatformCreationParams(params)
  ..setJavaScriptMode(JavaScriptMode.unrestricted);
Backfill ads in WebView requires adrop-ads-backfill module. If the module is not installed, registerWebView() is silently ignored.

Handling External URLs

If your app opens non-own-domain URLs in an external browser, you must ensure that ad resource requests (e.g., googleads.g.doubleclick.net) are not blocked. Ad resources such as iframes and scripts are loaded automatically by the ad SDK — they are not user-initiated navigations. Only redirect main frame navigations to an external browser.
import 'package:url_launcher/url_launcher.dart';

const allowedHost = 'my-domain.com';

_controller = WebViewController.fromPlatformCreationParams(params)
  ..setJavaScriptMode(JavaScriptMode.unrestricted)
  ..setNavigationDelegate(
    NavigationDelegate(
      onNavigationRequest: (NavigationRequest request) {
        final host = Uri.parse(request.url).host;

        // Only redirect main frame navigations to external browser
        // Ad resources (e.g., googleads.g.doubleclick.net) load via iframes/scripts —
        // do not block them
        if (!host.contains(allowedHost) && request.isMainFrame) {
          launchUrl(Uri.parse(request.url), mode: LaunchMode.externalApplication);
          return NavigationDecision.prevent;
        }
        return NavigationDecision.navigate;
      },
    ),
  );
Do not block or redirect all non-own-domain requests. Ad resources like googleads.g.doubleclick.net are loaded automatically during the backfill ad process and must be allowed to load within the WebView.

Banner Ads

Learn how to integrate banner ads

Reference

API reference

Examples

Example repository