📢

Mapbox 地図にMapbox広告を表示してみよう iOS編

2022/12/20に公開約11,300字

この記事は Mapbox Advent Calendar 2022 の 21日目の記事です。

はじめに

本記事はMapbox地図の上にMapbox広告を表示してみよう!という内容です。もしまだMapbox地図を使ったことがないという方は、下記の記事を参考に地図を表示するところから挑戦してみいただければと思います!

https://zenn.dev/capotasto/articles/7cbbac3f8edd92

Mapbox広告とは

広告の表示方法の前に簡単にMapbox広告について紹介させていただきたいと思います。

Mapbox広告とは、現在マップボックス・ジャパン合同会社が主導して開発を進めている、デジタル地図上に広告を配信することができる、新しい形の広告プラットフォームです。

https://www.mapbox.jp/ads

現在Mapbox広告として採用しているのは「プロモーテッド・ピン」という種類の広告になります。プロモーテッド・ピンは、地図上に広告主任意のデザインの広告ピンを表示でき、アプリユーザがピンをタップすると広告カードが表示されます。

広告カードには、基本情報はもちろん、動画バナーやお得なニュース、商品情報、写真などが表示されます。(表示内容は広告掲載プランによって異なります。広告について詳しくはこちらからお願いします)

このように広告主のピンやカードを表示することで、地図を利用したサービスでも簡単にマネタイズにつなげることが可能です。(マネタイズの詳細についてもこちらにお願いします)




地図に広告を表示してみよう

Mapbox広告を利用するには、Mapbox Ads SDKを使うことで簡単に実装が可能になっています。

Mapbox Ads SDK for iOS の 入手方法

早速試してみたい!と思われた方大変申し訳ありません。Mapbox Ads SDK for iOS は現在まだ非公開のSDKとなっておりますので、まずはこちらからご連絡をお願いします。

今後の開発予定にモジュールの公開(CocoapodsとSwift Package Manager)と、ソースコードのOSS化も検討しています。

Mapbox Ads SDK for iOS の 利用条件

Mapbox Ads SDK for iOS は現状 CocoapodsインストールMapbox Maps SDK for iOS へのみ対応しております。
Mapbox Maps SDK for iOS は Swift Package Manager をサポートを開始しているため、Mapbox Ads SDK for iOS についても開発を進めております。

準備 その1

さて、SDKを入手された方は以下より先に進んで頂ければと思います。
SDKは、.xcframeworkという拡張子となっております。こちらのファイルを Xcode上の任意のフォルダ(ここではFrameworksとします)にドラッグアンドドロップします。

すると、以下のようなウィンドが表示されるので、チェックを入れてFinishボタンを押します。

ファイルがコピーされていることを確認します。

プロジェクトファイル > Targets > アプリのスキーマ -> Frameworks, Libraries, and Embeded Content を確認して、.xcframework が追加されているので、Embed 設定を Do Not Embed から Embed & Signへ変更する

準備 その2

つづいて、以下の記述を Podfile へ追記して、 pod install します。

Podfile
# Uncomment the next line to define a global platform for your project
platform :ios, '13.0'

target 'MapboxPromotedAdsDemo' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!
  pod 'MapboxMaps', '10.9.1'
end

+ post_install do |installer|
+  installer.pods_project.targets.each do |target|
+    target.build_configurations.each do |config|
+      config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
+    end
+  end
+ end

導入 その1

SDKのインストールが完了したので、広告を表示するソースコードを記載していきます。
まずは、SDK本体となる MapboxPromotionManager を以下のように初期化します。初期化するタイミングは、必ず 地図画面が表示される画面が初期化されるタイミングで行うようにしてください。

ViewController.swift
...
+ import MapboxPromoted

class ViewController: UIViewController {
...
+ private let promotionsManager = MapboxPromotionManager()
...
}

導入 その2

続いて、MapboxPromotionDelegateを実装してSDKからの必要なコールバックを記述していきます。これらは、広告ピンが表示され、アプリのユーザがピンをタップした際に表示される広告カードの表示やユーザアクションのコールバックをアプリ側へ通知されるために使用されます。各デリゲートメソッドの解説はこちらをご確認ください。

ViewController.swift
extension ViewController: MapboxPromotionDelegate {
    func promotionManager(
        _: MapboxPromotionManager,
        didSelect card: MapboxPromotedMBPCardView,
        promotion: MapboxPromotion
    ){
        card.attach(to: view, animated: true, completion: nil)
    }

    func promotionManager(
        _: MapboxPromotionManager,
        didDeselect card: MapboxPromotedMBPCardView,
        promotion _: MapboxPromotion
    ){
        card.detach(from: view, animated: true)
    }

    func promotionManager(
        _: MapboxPromotionManager,
        showAttribution controller: MapboxAdsAttributionViewController
    ){
        present(controller, animated: true, completion: nil)
    }

    func promotionManager(
        _: MapboxPromotionManager,
        closeAttribution controller: MapboxAdsAttributionViewController
    ){
        controller.dismiss(animated: true)
    }

    func promotionManager(
        _: MapboxPromotionManager,
        didTapCard action: MapboxPromotedMBPCardTapAction,
        promotion: MapboxPromotion
    ){
        print("didTapCard: \(action)")
    }

    func promotionManager(
        _: MapboxPromotionManager,
        didTransitionCard state: MapboxPromotedMBPCardTransition
    ){
        print("did transition state:\(state)")
    }
}

導入 その3

ここまでくればもうすぐ完了です。Mapのロードが完了した(mapLoaded)タイミングで、loadPromotions を呼び出して広告のロードしましょう。その際、必ず .staging 環境を指定しましょう。

ViewController.swift
override public func viewDidLoad() {
    super.viewDidLoad()
    ....
    
+    mapView.mapboxMap.onNext(event: .mapLoaded) { [weak self] _ in
+        guard let self = self,
+              let mapView = self.mapView,
+              let layer = mapView.mapboxMap.style.allLayerIdentifiers.last?.id else {
+            return
+        }
+
+        self.promotionsManager.loadPromotions(
+            for: mapView,
+            below: layer, // 任意のレイヤーの下に表示したい場合に指定
+            with: .staging) // Staging 環境を指定
+        self.promotionsManager.delegate = self // その2で実装したMapboxPromotionDelegateを設定する
+    }
}

実行結果

実行結果は以下のようになります。Staging環境のため表示されているピンや広告カードの内容は仮のものになります。

広告ピン 広告カード1 広告カード2

コード全体

最後に ViewController.swift のコード全体は以下になります

ViewController.swift
import UIKit
import MapboxMaps
import MapboxPromoted

class ViewController: UIViewController {

    internal var mapView: MapView!
    private let tokyoStation = CLLocationCoordinate2D(latitude: 35.6812, longitude: 139.7671)
    private let promotionsManager = MapboxPromotionManager()

    override public func viewDidLoad() {
        super.viewDidLoad()
        let token = Bundle.main.object(forInfoDictionaryKey: "MBXAccessToken") as? String ?? ""

        let option = MapInitOptions(
            resourceOptions: ResourceOptions(accessToken: token),
            cameraOptions: CameraOptions(center: tokyoStation, zoom: 14.5)
        )
        mapView = MapView(frame: view.bounds, mapInitOptions: option)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

        self.view.addSubview(mapView)

        mapView.mapboxMap.onNext(event: .mapLoaded) { [weak self] _ in
            guard let self = self,
                  let mapView = self.mapView,
                  let layer = mapView.mapboxMap.style.allLayerIdentifiers.last?.id else {
                return
            }

            self.promotionsManager.loadPromotions(
                for: mapView,
                below: layer, // this is optional
                with: .staging) // ".staging" for development or ".production" for production.
            self.promotionsManager.delegate = self
        }
    }
}

extension ViewController: MapboxPromotionDelegate {
    func promotionManager(
        _: MapboxPromotionManager,
        didSelect card: MapboxPromotedMBPCardView,
        promotion: MapboxPromotion
    ){
        card.attach(to: view, animated: true, completion: nil)
    }

    func promotionManager(
        _: MapboxPromotionManager,
        didDeselect card: MapboxPromotedMBPCardView,
        promotion _: MapboxPromotion
    ){
        card.detach(from: view, animated: true)
    }

    func promotionManager(
        _: MapboxPromotionManager,
        showAttribution controller: MapboxAdsAttributionViewController
    ){
        present(controller, animated: true, completion: nil)
    }

    func promotionManager(
        _: MapboxPromotionManager,
        closeAttribution controller: MapboxAdsAttributionViewController
    ){
        controller.dismiss(animated: true)
    }

    func promotionManager(
        _: MapboxPromotionManager,
        didTapCard action: MapboxPromotedMBPCardTapAction,
        promotion: MapboxPromotion
    ){
        print("didTapCard: \(action)")
    }

    func promotionManager(
        _: MapboxPromotionManager,
        didTransitionCard state: MapboxPromotedMBPCardTransition
    ){
        print("did transition state:\(state)")
    }
}

最後に

いかがでしょうか?思ったよりも簡単に表示できるなと感じていただけたのではないでしょうか?
まだ未公開な部分もありますが、順次公開に向けて進めております。もし地図サービスのマネタイズに興味のある方、地図上に広告を出してみたい方は下記から問い合わせをお願いします!

https://www.mapbox.jp/contact


各デリゲートメソッドについての解説

MapboxPromotionDelegateのデリゲートメソッドについての解説です。

メソッド 解説
didSelect 広告のピンをタップした際に呼び出されます。サンプルのようにMapboxPromotedMBPCardView#attachを使用してviewを渡すことで、広告カードを表示させることができます。
didDeselect 広告カードが表示されている状態で、地図エリアがタップされた際など広告カードを閉じる必要がある際に呼び出されます。MapboxPromotedMBPCardView#detachを呼び広告カードを閉じることができます。
showAttribution 広告カード内にある「広告」ボタンがタップされた際に呼び出されます。広告に関する説明ViewとしてMapboxAdsAttributionViewControllerの表示できます。
closeAttribution 広告に関する説明View内にある「完了」ボタンがタップされたら呼び出されます。MapboxAdsAttributionViewControllerの非表示できます。
didTapCard 広告カード内にあるその他各種ボタン(詳細はこちら)がタップされたら呼び出されます。下記の詳細を参考に各ボタンタップの際に追加で処理を行いたい場合は追加できます。なお、MapboxPromotedMBPCardTapActionオブジェクトが externalLinkの場合はURL情報が内包されていますので、基本的外部ブラウザ等で表示することが可能です。
didTransitionCard 広告カードの状態が変更になった際に呼び出されます。全画面表示(expanded), 画面下部表示(collapsed), 非表示(closed)の状態が通知されます。

各種タップイベントの種類

MapboxPromotedMBPCardTapActionの各イベントについての解説です。

タイプ 説明
route カード内の「経路」ボタンをタップ時に呼ばれます。ルート検索画面を表示してください。
navigation カード内のナビゲーション表示のアクション時に呼ばれます。ナビゲーション画面を表示してください。(現在ナビゲーションボタンは非表示になっています)
businessHours カード内の営業時間の項目をタップした時に呼ばれます。営業時間の項目が開閉されます。特に実装の必要はありません。
address カード内の住所の項目をタップした時に呼ばれます。特に実装の必要はありません。
externalLink カード内の各種外部リンクボタンをタップ時に呼ばれます。下記を参考に、外部ブラウザ/内部ブラウザへの遷移を行なってください。

カード内の各種外部リンクボタンの種類

MapboxPromotedMBPCardTapActionイベントがexternalLink場合のMapboxPromotedMBPCardLinkTypeについての解説です。

タイプ 説明 備考
call カード内の「電話」ボタン/「電話」の項目をタップ時に呼ばれます。外部ブラウザへの遷移を行なってください。 e.g. tel:03-0000-0000
banner カード内のバーナー画像をタップ時に呼ばれます。外部ブラウザ/内部ブラウザへの遷移を行なってください。 e.g. https://www.mapbox.jp/ads
detailSite カード内の「公式サイト」ボタン/公式サイトの項目をタップ時に呼ばれます。外部ブラウザ/内部ブラウザへの遷移を行なってください。 e.g. https://www.mapbox.jp/ads
attributionLink カード内の「この広告について」の画面「Mapbox広告ページへ」をタップ時に呼ばれます。外部ブラウザ/内部ブラウザへの遷移を行なってください。 e.g. https://www.mapbox.jp/ads
line カード内の「公式LINE」ボタンをタップ時に呼ばれます。外部ブラウザ/内部ブラウザへの遷移を行なってください。 e.g. https://line.me/R/
appStore カード内の「App Store」ボタンをタップ時に呼ばれます。外部ブラウザ/内部ブラウザへの遷移を行なってください。 e.g. https://apps.apple.com/app-name
twitter カード内の「Twitter」ボタンをタップ時に呼ばれます。外部ブラウザ/内部ブラウザへの遷移を行なってください。 e.g. https://twitter.com/page
facebook カード内の「Facebook」ボタンをタップ時に呼ばれます。外部ブラウザ/内部ブラウザへの遷移を行なってください。 e.g. https://facebook.com/page
instagram カード内の「Instagram」ボタンをタップ時に呼ばれます。外部ブラウザ/内部ブラウザへの遷移を行なってください。 e.g. https://instagram.com/page

Discussion

ログインするとコメントできます