Flutter Webでの収益化: 広告枠をWidgetとして扱う


Flutter Webは、クロスプラットフォーム開発の強力なフレームワークです。
今回は、Flutter Webを使用して、ウェブページに広告を表示するためのカスタムウィジェットを作成する方法について説明します。

## 目的

`web`ディレクトリ直下の`index.html`を編集し、ページ下部に広告を追加することができますが、この方法ではページに合わせて広告の見せ方をカスタマイズするのが難しいことがあります。
そこで、Widgetとして広告枠を扱い、ページ構成に合わせて自由に広告を配置できるようにします。
具体的には`IFrame`を利用して広告用のHTMLファイルをページ内に部分的に表示できるようにします。

## 広告用HTMLを用意する

広告を表示するためには、特定の広告スクリプトをロードするHTMLファイルが必要です。
HTMLは`web`ディレクトリ直下に放り込んでおけば良いかと思います。

ここでは手っ取り早く広告を試すために、[忍者AdMax](https://admax.shinobi.jp/)を使用しています。

```html
<!DOCTYPE html>
<html>
<head>
<title>Ads View</title>
</head>
<body>
<!-- admax -->
<script src="https://adm.shinobi.jp/s/xxx..."></script>
<!-- admax -->
</body>
</html>
```

## カスタム広告ウィジェットの作成

以下は、広告を表示するためのカスタムウィジェット`CustomAdsView`の例です。
前述の広告用HTMLファイルへのパスを引数`adsSrc`で受け取り、コンストラクタ内で`IFrameElement`を使用して広告を表示するためのビューを登録します。
サイズは広告に合わせて調整します。

```dart
import 'dart:html';
import 'dart:ui' as ui;

import 'package:flutter/material.dart';

class CustomAdsView extends StatelessWidget {
  CustomAdsView({
    super.key,
    required this.adsId,
    required String adsHeight,
    required String adsWidth,
    required String adsSrc,
    required this.viewHeight,
    required this.viewWidth,
  }) {
    ui.platformViewRegistry.registerViewFactory(
      adsId,
      (int viewID) => IFrameElement()
        ..style.height = adsHeight
        ..style.width = adsWidth
        ..src = adsSrc
        ..style.border = 'none',
    );
  }

  final String adsId;
  final double viewHeight;
  final double viewWidth;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: viewHeight,
      width: viewWidth,
      child: HtmlElementView(
        viewType: adsId,
      ),
    );
  }
}

```


## 使用方法

`CustomAdsView`ウィジェットを使用することで、`ListView`の中に自然な形で広告を入れられます。
Streamとかで頑張れば一定時間ごとに広告ウィジェットの描画をリフレッシュするなどの動作も実現できます。

### CustomAdsViewの使い方

以下の感じで使います。

```dart
  CustomAdsView(
    adsId: "square_ads_view",
    adsHeight: "280px",
    adsWidth: "320px",
    adsSrc: "square_ads_view.html",
    viewHeight: 280,
    viewWidth: 300,
  )
```

### ListViewへの組み込み例

![スクリーンショット 2023-08-15 13.24.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478047/cf3eedbc-a4ed-3da2-26d3-79caf1a595ed.png)

上記画面の実装は以下の通り。

```dart
import 'package:flutter/material.dart';
import 'package:warchest_dojo/widget/ads_view/custom_ads_view.dart';

class AdsSamplePage extends StatelessWidget {
  const AdsSamplePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("テスト用"),
      ),
      body: Center(
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            CustomAdsView(
              adsId: "vertical_banner_ads_view_1",
              adsHeight: "700px",
              adsWidth: "200px",
              adsSrc: "vertical_banner_ads_view_1.html",
              viewHeight: 700,
              viewWidth: 200,
            ),
            SizedBox(
              width: 320,
              child: ListView(
                children: [
                  const Card(
                    child: ListTile(
                      title: Text("テスト"),
                    ),
                  ),
                  const Card(
                    child: ListTile(
                      title: Text("テスト"),
                    ),
                  ),
                  CustomAdsView(
                    adsId: "square_ads_view",
                    adsHeight: "320px",
                    adsWidth: "320px",
                    adsSrc: "square_ads_view.html",
                    viewHeight: 280,
                    viewWidth: 300,
                  ),
                  const Card(
                    child: ListTile(
                      title: Text("テスト"),
                    ),
                  ),
                  const Card(
                    child: ListTile(
                      title: Text("テスト"),
                    ),
                  ),
                ],
              ),
            ),
            CustomAdsView(
              adsId: "vertical_banner_ads_view_2",
              adsHeight: "700px",
              adsWidth: "200px",
              adsSrc: "vertical_banner_ads_view_2.html",
              viewHeight: 700,
              viewWidth: 200,
            ),
          ],
        ),
      ),
    );
  }
}
```

## まとめ

Flutter Webを使用して広告をウィジェットとして扱うことで、ウェブページに柔軟に広告を配置することが可能になります。
これにより、デザインと機能性の両方を最大限に活用することができます。

## 参考

https://stackoverflow.com/questions/63985740/how-to-insert-adsense-display-ad-in-flutter-web

## その他

趣味でAIと対戦できるボードゲームをFlutter webだけで作ってます。

https://warchest-dojo.app/