半年ほど前にAppBrewに入社した奈良阪です。 メインはLIPSのサーバーサイド・フロントエンド、たまにインフラ、最近アプリに手を出しつつ、新規事業の方のベースのライブラリを書いてたり諸々しています。
さて、AppBrewでは現在幅広い広告主との取組みが増やせるよう、様々な広告枠の開発、実装にチャレンジしています。 その一環として、最近Googleアドマネージャーの「インタースティシャル広告」機能を利用して、LIPSにモバイルアプリ向け静止画全画面広告を実装しました。
しかしこれを実装するにあたってGoogle公式のドキュメントを参照したのですが、インタースティシャル広告についての項目は他の項目と混ざっており、いまいちドキュメントがまとまっていませんでした。
公式以外のWeb上にもあまり一連で書いたものが見当たらず、全画面広告実装に必要な情報を収集するのにやや苦労したので以下にまとめます。
基本的に公式ドキュメントは、運用的なガイドやおおまかな仕様がGoogle アド マネージャー ヘルプ、実装上のものがMobile Ads SDKと異なる場所にあり、さらに前者のヘルプの中であまり順序立ててリンクが張られていないため、あちこちを飛びながら参照する形になります。
Google アドマネージャーを初めて使う中でドキュメントを見ながら実際に広告を実装するにあたって遭遇した注意点などを追っていき、分散したドキュメントでもある程度スムーズに進められるよう記述してゆきます。
Google アドマネージャーとは
Google アドマネージャーはWebの「広告配信」を管理するツールです。 ウェブサイト、モバイルアプリ問わず使えて、様々な形式の広告が出せます。
Web広告の形式として最もポピュラーなのは、Webサイトやモバイルアプリの画面の一部に四角い画像が出てくる、いわゆるバナー広告と呼ばれるものだと思います。 アドマネージャーにもずばり「バナー広告」というメニューがあり、これをサイトやアプリに簡単に実装できます。
そして今回のターゲットであるモバイルアプリの全画面広告を実装する場合、「インタースティシャル広告」というメニューを使います。
インタースティシャル広告とは
Googleアドマネージャーのインタースティシャル広告はアプリに全画面広告が表示できる機能です。 が、単に全画面というわけではなく、「コンテンツ間に表示される」ように設計されているものです1。
おおまかには画面切り替えの時に表示する事が推奨されており、今回は「アプリ起動→ローディング画面→インタースティシャル広告→ホーム画面」という遷移で表示することにしました。
ポリシーに準拠する
インタースティシャル広告の利用時には、ユーザーが不便に思い結果的にユーザーが離れるような好き勝手な実装はしないようにとインタースティシャル広告のポリシーが定められています。 このポリシーに関しては上記のページにまとまっているためあまり迷うことは無いと思います。
おおまかには「操作を妨げない」、「誤タップを誘わない」が原則で、それに基づいた細則が定められています。例えば動画広告でない場合は常時閉じるボタンを表示する必要があることなどですね。
特徴的なところでは、起動したら最初にインタースティシャル広告を表示するのは「コンテンツ間に表示される」に違反しているのでNGという例が書いてあります。
出典: 許可されないインタースティシャル広告の実装例 より(説明部分は日本語訳しました)
実装方法
ポリシーに準拠した仕様が定まったら実装をしていきます。
クライアント実装については、Mobile Ads SDKドキュメントのiOS、Androidそれぞれのトップからすぐインタースティシャル広告の項目へ飛べます。
基本的にそのまま実装すれば良いですが、注意点としてdidFailToReceiveAdWithErrorイベントは通信失敗などの異常系以外にも、広告枠にその時点で広告が設定されてない場合や、広告のフリークエンシー制御でそのユーザーに配信する広告がない場合にも発火します。iOS側のドキュメントにも
interstitial:didFailToReceiveAdWithError: メソッドから新しい広告の読み込みを試行することは避けてください。
と書いてあるように、異常系のように見える名前ですがこのイベントで特別異常処理をするべきではなさそうです。
入稿
さて、クライアントの準備が済んだら一旦広告を表示してみましょう。
Google アドマネージャーでは広告の枠を定義する「在庫」と、そこに実際の広告受注を当て込む「配信」の概念が存在します。 Mobile Ads SDKドキュメントに出てきた「広告ユニット」というのは「在庫」の概念です。
在庫を定義
「広告ユニットを作成する」に従ってインタースティシャル広告用の広告枠を定義します。
ただし、モバイルアプリ用インタースティシャル広告においては、なんとここの設定項目にある広告枠の物理的な「サイズ」には実際の表示サイズを入れません。
「アプリ内インタースティシャルを作成する」にあるように、iPhone, Androidスマートフォン向けには320x480(縦)または480x320(横)、iPadなどタブレットデバイス向けには1024x768(横)または 768x1024(縦)にする必要があります。
普通に入力しようとすると、サイズ指定の所に「ページ外 (インタースティシャル広告)」と勢いよく出てくるのですが、これを無視して数値の方の値を入れます。なかなか妙な仕様です。
配信を開始
「オーダーを作成する」、「広告申込情報を作成する」に従ってオーダーと広告申込情報を作成します。
この広告申込情報においても、サイズ指定の所に320x480等の固定値を入れます。妙な仕様です。
この広告申込情報に画面に実際に配信される広告(クリエイティブ)を紐付けることで配信ができます。
クリエイティブテンプレート
インタースティシャル広告のクリエイティブは、モバイルアプリ用であってもブラウザで表示できるHTMLで構成します。
Google アドマネージャーの「クリエイティブテンプレート」にHTMLを書き、プレースホルダーを実際の広告クリエイティブ情報(画像や文言、クリック遷移先等)で埋めることで実際にクリエイティブとするのが定石です。
クリエイティブ テンプレートの作成と管理の「標準のクリエイティブ テンプレート」に一覧されているうち、「モバイル インタースティシャルと自動クローズ(アプリ)」(Mobile Interstitial with Auto-close (app))がインタースティシャル広告用のデフォルトのクリエイティブテンプレートです。
しかしこのクリエイティブテンプレートは
- 閉じるボタンが開くタイミングによってランダムに左右に振れて操作性が悪い(おそらくユーザーが慣れて広告を即閉じるのを防止するため)
- 小さい閉じるボタン以外どこをタップしても遷移する
というもので、それこそ誤タップが発生しそうなものです。
今回はアプリを使っている間に定期的に不意に出る広告というわけではなく、起動時のみに出る比較的上品な印象に作る必要があったため、
- 閉じるボタンは大きく固定位置
- 遷移用のタップボタンを配置しそれ以外の領域は反応しない
という要件のクリエイティブテンプレートをカスタマイズして作ることとしました。
カスタムクリエイティブテンプレートを作る
プレースホルダーや基本的な動作などは標準のクリエイティブテンプレートに従うのが楽なため、「モバイル インタースティシャルと自動クローズ(アプリ)」をコピーして「カスタムクリエイティブテンプレート」を作成します。
これをフォーム上で上書き配信して逐一確認するのではUIを作るイテレーションが遅いため、Webpackを利用してPCブラウザで簡易的に確認しつつ開発し、ビルドしてminifyしたコードをGoogleアドマネージャーのフォームに貼り付ける形としました。
HTML/CSS/JavaScriptはもちろん、url-loaderを使えば閉じるボタンなどの小さい画像も外部参照無く1ソースで最小化して同梱できます。テキストなのでたかが知れている所はありつつも、やはりできる限り小さいサイズで配信したいですし、アドマネージャーから外部依存は無い方が面倒もなくなります。
「閉じるボタン」カスタマイズ
さて、標準のクリエイティブテンプレートで表示される左右に振れる閉じるボタンはHTML上ではなくクライアントのSDKが出しているものですが、これはHTMLで書かれたクリエイティブテンプレート側から表示を操作できます。
Google アドマネージャーのクリエイティブではMRAID(Mobile Rich media Ad Interface Definitions)という統一のクリエイティブで広告配信可能なように規定された標準規格APIを利用できるようになっています。
「Google Mobile Ads SDK の広告を作成する」に詳細がありますが、<script src="mraid.js"></script>
を書き、mraid.useCustomClose(true);
を実行すればデフォルトの閉じるボタンは出なくなります。
あとはdocument.querySelector("#closeButton").addEventListener(function () { admob.opener.close(); });
などとカスタムのクローズイベントをカスタムボタンに紐付ければ動作します。
なおadmob.opener.close();
は標準のクリエイティブテンプレートから書かれているAdMob API for AdsのAPIです。
全体的なサンプルは同ドキュメント内「アプリ内広告のサンプルコード: カスタムの閉じるボタンを使用したモバイル エキスパンド バナー(MRAID 2.0)」に詳しいです(バナー用なのでインタースティシャルに適宜置き換える必要はあります)。
MRAIDのその他のAPIはアプリ内インタースティシャルを作成するなどから飛べます。
dispatchAppEvent
また実際に配信した際に事前に予測していた表示頻度と乖離があったため、詳しい状態を知るためにログを仕込むということもしました。
このとき「タップした」「閉じた」などの標準的なイベントは上であげた実装ドキュメントのGADInterstitialDelegate
(iOS)等に詳しいのですが、HTML上からカスタムのイベントを送ることもできます。
AdMob API for Adsにadmob.events.dispatchAppEvent(name, opt_info, opt_sendBeforePageLoad)
というAPIがあり、これを叩くとクライアント側でイベントを受け取ることができます。
クライアント側の実装ですが、GADInterstitialDelegate
(iOS)と別のGADAppEventDelegate(iOS)というものがあり、ここにfunc interstitial(_ interstitial: GADInterstitial, didReceiveAppEvent name: String, withInfo info: String?)
を実装すると受け取れます。
-class ViewController: UIViewController, GADInterstitialDelegate { +class ViewController: UIViewController, GADInterstitialDelegate, GADAppEventDelegate { var interstitial: DFPInterstitial! override func viewDidLoad() { super.viewDidLoad() interstitial = DFPInterstitial(adUnitID: "/6499/example/interstitial") interstitial.delegate = self + interstitial.appEventDelegate = self } + + func interstitial(_ interstitial: GADInterstitial, didReceiveAppEvent name: String, withInfo info: String?) { + print("interstitial " + name) + } ... }
これはインタースティシャルのドキュメントには存在しない記述ですが、Banner Adsのドキュメントに同様のものがあります。
おわりに
結構散らばったドキュメント群や分かりにくい部分の補足を実装面からは比較的追えたのではと思います。
まだ利用していない機能やドキュメントの記述などもあるとは思いますが、皆さんの実装時に参考になれば幸いです。
We are Hiring!
弊社AppBrewでは現在、500万DL突破のコスメクチコミアプリ「LIPS」をはじめとした「ユーザーが熱狂するプロダクト」を、「再現性をもって開発すること」に携わるエンジニアを積極採用中です。
目的に真摯に向き合い、技術でそれを解決したいと思うエンジニアの方はぜひ一度ご応募ください!お待ちしております。