> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adrop.io/llms.txt
> Use this file to discover all available pages before exploring further.

# WebView Guide

> How to display backfill ads in WebView for Flutter

## 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:

```bash theme={null}
flutter pub add webview_flutter webview_flutter_android webview_flutter_wkwebview
```

<Warning>
  WebView backfill ads require `adrop-ads-backfill` to be configured on both Android and iOS. See [Getting Started](/sdk/flutter/overview) for setup instructions.
</Warning>

***

## Platform Configuration

Configure the native platforms to enable backfill ads in WebView.

<Tabs>
  <Tab title="Android">
    Add the following to `android/app/src/main/AndroidManifest.xml`:

    ```xml AndroidManifest.xml theme={null}
    <manifest>
        <application>
            <!-- WebView Backfill Ad Integration -->
            <meta-data
                android:name="com.google.android.gms.ads.INTEGRATION_MANAGER"
                android:value="webview"/>
        </application>
    </manifest>
    ```
  </Tab>

  <Tab title="iOS">
    Add the following key to `ios/Runner/Info.plist`:

    ```xml Info.plist theme={null}
    <key>GADIntegrationManager</key>
    <string>webview</string>
    ```
  </Tab>
</Tabs>

<Warning>
  This configuration is required for backfill ads to work properly in WebView. Without it, backfill ads may not display.
</Warning>

***

## Register WebView

Create a `WebViewController`, extract the platform-specific identifier, and register it with `Adrop.registerWebView` before loading content.

```dart theme={null}
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:

| Platform | Controller                 | Property             |
| -------- | -------------------------- | -------------------- |
| Android  | `AndroidWebViewController` | `.webViewIdentifier` |
| iOS      | `WebKitWebViewController`  | `.webViewIdentifier` |

```dart theme={null}
if (Platform.isAndroid) {
  identifier =
      (_controller.platform as AndroidWebViewController).webViewIdentifier;
} else if (Platform.isIOS) {
  identifier =
      (_controller.platform as WebKitWebViewController).webViewIdentifier;
}
```

<Note>
  Call `Adrop.registerWebView()` before loading any web content. Load the URL only after registration is complete.
</Note>

***

## iOS WebView Configuration

For iOS, configure inline media playback using `WebKitWebViewControllerCreationParams`:

```dart theme={null}
final params = WebKitWebViewControllerCreationParams(
  allowsInlineMediaPlayback: true,
  mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
);

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

<Warning>
  Backfill ads in WebView requires `adrop-ads-backfill` module. If the module is not installed, `registerWebView()` is silently ignored.
</Warning>

***

## 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.

```dart theme={null}
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;
      },
    ),
  );
```

<Warning>
  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.
</Warning>

***

## Related Documentation

<CardGroup cols={2}>
  <Card title="Banner Ads" icon="rectangle-ad" href="/sdk/flutter/banner">
    Learn how to integrate banner ads
  </Card>

  <Card title="Reference" icon="book" href="/sdk/flutter/reference">
    API reference
  </Card>

  <Card title="Examples" icon="code" href="/sdk/flutter/examples">
    Example repository
  </Card>
</CardGroup>
