Skip to content

バナーの配置を管理する

Braze SDKでバナー広告枠の作成と管理方法を学ぶ。これには、広告枠固有のプロパティへのアクセスやインプレッションの記録が含まれる。一般的な情報については、バナーについてを参照してください。

配置依頼について

アプリやWeb サイトで配置を作成すると、アプリは各配置に対応するバナーメッセージを取得するため、Brazeにリクエストを送信する。

  • 1回の更新リクエストにつき、最大10の配置をリクエストできる。
  • 各配置において、Brazeはユーザーが受け取る資格のある最高優先度のバナーを返す。
  • リフレッシュ時に10件を超える配置が要求された場合、最初の10件のみが返され、残りは破棄される。

例えば、アプリがリフレッシュリクエストで3つの配置を要求する場合がある: homepage_promo, cart_abandonment, および seasonal_offer。各リクエストは、その配置に対して最も関連性の高いバナーを返す。

更新リクエストのレート制限

古いSDKバージョン(SWIFT 13.1.0以前、Android 38.0.0以前、Web 6.1.0以前、React Native 17.0.0以前、Flutter 15.0.0以前)を使用している場合、ユーザーセッションごとにリフレッシュリクエストは1回のみ許可される。

新しい最小SDKバージョン(SWIFT 13.1.0以上、Android 38.0.0以上、Web 6.1.0以上、React Native 17.0.0以上、Flutter 15.0.0以上)を使用している場合、リフレッシュリクエストは過剰なポーリングを防ぐためトークンバケットアルゴリズムでコントロールされる:

  • 各ユーザーセッションは、5つのリフレッシュトークンから始まる。
  • トークンは180秒(3分)ごとに1個補充される。

各呼び出しはトークンをrequestBannersRefresh一つ消費する。トークンが利用できない状態で更新を試みると、SDKはリクエストを送信せず、トークンが補充されるまでエラーをログに記録する。これはセッション途中やトリガー発生時の更新において重要だ。ダイナミックな更新を実装する場合(例えば、ユーザーが同じページでアクションを完了した後など)、カスタムイベントが記録された後にリフレッシュメソッドを呼び出す。ただし、ユーザーが別のバナーキャンペーンの対象となる前に、Brazeがイベントを取り込んで処理するのに必要な遅延に注意すること。

配置を作成

前提条件

バナー配置を作成するために必要な最小限のSDKバージョンは以下の通りだ:

ステップ 1: Braze での配置の作成

まだ作成していない場合は、アプリまたはサイトでバナーを表示できる場所を定義するために使用するバナーの配置をBrazeで作成する必要があります。配置を作成するには、Settings > Banners Placementsに移動し、配置の作成を選択します。

配置ID を作成するためのバナー配置セクション。

配置に名前を付け、配置ID を割り当てます。ID はカードのライフサイクル全体で使用されるため、後で変更しないでください。ID を割り当てる前に、他のチームに相談してください。詳細については、配置IDを参照してください。

バナーを指定する配置の詳細は、バネ販売促進キャンペーンsの左側のサイドバーに表示されます。

ステップ 2:アプリの配置を更新する

配置は、以下に説明する更新メソッドを呼び出すことで更新できる。これらの配置は、ユーザーのセッションが期限切れになった時、または`changeUsermethod`を使用して識別子を使用してユーザーを変更した時に自動的にキャッシュされる。

1
2
3
import * as braze from "@braze/web-sdk";

braze.requestBannersRefresh(["global_banner", "navigation_square_banner"]);
1
AppDelegate.braze?.banners.requestRefresh(placementIds: ["global_banner", "navigation_square_banner"])
1
2
3
4
ArrayList<String> listOfBanners = new ArrayList<>();
listOfBanners.add("global_banner");
listOfBanners.add("navigation_square_banner");
Braze.getInstance(context).requestBannersRefresh(listOfBanners);
1
Braze.getInstance(context).requestBannersRefresh(listOf("global_banner", "navigation_square_banner"))
1
Braze.requestBannersRefresh(["global_banner", "navigation_square_banner"]);
1
This feature is not currently supported on Unity.
1
This feature is not currently supported on Cordova.
1
braze.requestBannersRefresh(["global_banner", "navigation_square_banner"]);
1
This feature is not currently supported on Roku.

ステップ 3:更新をリッスンする

Web Braze SDKとvanilla JavaScriptを使用している場合、`eventsubscribeToBannersUpdates.onで配置更新を監視し、event.onを[requestBannersRefresh`](https://js.appboycdn.com/web-sdk/latest/doc/modules/braze.html#requestbannersrefresh)呼び出して取得する。

1
2
3
4
5
6
7
8
import * as braze from "@braze/web-sdk";

braze.subscribeToBannersUpdates((banners) => {
  console.log("Banners were updated");
});

// always refresh after your subscriber function has been registered
braze.requestBannersRefresh(["global_banner", "navigation_square_banner"]);

Web Braze SDKでReactを使用している場合、リスナーを登録した後、フックuseEffect内でsubscribeToBannersUpdates設定requestBannersRefreshし、を呼び出すこと。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import * as braze from "@braze/web-sdk";

useEffect(() => {
  const subscriptionId = braze.subscribeToBannersUpdates((banners) => {
    console.log("Banners were updated");
  });

  // always refresh after your subscriber function has been registered
  braze.requestBannersRefresh(["global_banner", "navigation_square_banner"]);

  // cleanup listeners
  return () => {
    braze.removeSubscription(subscriptionId);
  }
}, []);
1
2
3
4
5
let cancellable = brazeClient.braze()?.banners.subscribeToUpdates { banners in
  banners.forEach { placementId, banner in
    print("Received banner: \(banner) with placement ID: \(placementId)")
  }
}
1
2
3
4
5
Braze.getInstance(context).subscribeToBannersUpdates(banners -> {
  for (Banner banner : banners.getBanners()) {
    Log.d(TAG, "Received banner: " + banner.getPlacementId());
  }
});
1
2
3
4
5
Braze.getInstance(context).subscribeToBannersUpdates { update ->
  for (banner in update.banners) {
    Log.d(TAG, "Received banner: " + banner.placementId)
  }
}
1
2
3
4
5
6
7
8
9
10
const bannerCardsSubscription = Braze.addListener(
  Braze.Events.BANNER_CARDS_UPDATED,
  (data) => {
    const banners = data.banners;
    console.log(
      `Received ${banners.length} Banner Cards with placement IDs:`,
      banners.map((banner) => banner.placementId)
    );
  }
);
1
This feature is not currently supported on Unity.
1
This feature is not currently supported on Cordova.
1
2
3
4
5
StreamSubscription bannerStreamSubscription = braze.subscribeToBanners((List<BrazeBanner> banners) {
  for (final banner in banners) {
    print("Received banner: " + banner.toString());
  }
});
1
This feature is not currently supported on Roku.

ステップ4:配置 ID を使って挿入する

バナーのコンテナ要素を作成する。幅と高さは必ず設定してください。

1
<div id="global-banner-container" style="width: 100%; height: 450px;"></div>

Web Braze SDKとvanilla JavaScriptを使用している場合、コンテナ要素の内部HTMLを置き換えるには`setContent`insertBannerメソッドを呼び出す。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import * as braze from "@braze/web-sdk";

braze.initialize("sdk-api-key", {
  baseUrl: "sdk-base-url",
  allowUserSuppliedJavascript: true, // banners require you to opt-in to user-supplied javascript
});

braze.subscribeToBannersUpdates((banners) => {
  // get this placement's banner. If it's `null` the user did not qualify for one.
  const globalBanner = braze.getBanner("global_banner");
  if (!globalBanner) {
    return;
  }

  // choose where in the DOM you want to insert the banner HTML
  const container = document.getElementById("global-banner-container");

  // Insert the banner which replaces the innerHTML of that container
  braze.insertBanner(globalBanner, container);

  // Special handling if the user is part of a Control Variant
  if (globalBanner.isControl) {
    // hide or collapse the container
    container.style.display = "none";
  }
});

braze.requestBannersRefresh(["global_banner", "navigation_square_banner"]);

Web Braze SDKとReactを使用している場合、コンテナ要素の内部HTMLを置き換えるには、`setContentinsertBannerメソッドrefを\HTML`オブジェクトと共に呼び出す。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { useRef } from 'react';
import * as braze from "@braze/web-sdk";

export default function App() {
    const bannerRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
       const globalBanner = braze.getBanner("global_banner");
       if (!globalBanner || globalBanner.isControl) {
           // hide the container
       } else {
           // insert the banner to the container node
           braze.insertBanner(globalBanner, bannerRef.current);
       }
    }, []);
    return <div ref={bannerRef}></div>
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// To get access to the Banner model object:
let globalBanner: Braze.Banner?
AppDelegate.braze?.banners.getBanner(for: "global_banner", { banner in
  self.globalBanner = banner
})

// If you simply want the Banner view, you may initialize a `UIView` with the placement ID:
if let braze = AppDelegate.braze {
  let bannerUIView = BrazeBannerUI.BannerUIView(
    placementId: "global_banner",
    braze: braze,
    // iOS does not perform automatic resizing or visibility changes.
    // Use the `processContentUpdates` parameter to adjust the size and visibility of your Banner according to your use case.
    processContentUpdates: { result in
      switch result {
      case .success(let updates):
        if let height = updates.height {
          // Adjust the visibility and/or height.
        }
      case .failure(let error):
        // Handle the error.
      }
    }
  )
}

// Similarly, if you want a Banner view in SwiftUI, use the corresponding `BannerView` initializer:
if let braze = AppDelegate.braze {
  let bannerView = BrazeBannerUI.BannerView(
    placementId: "global_banner",
    braze: braze,
    // iOS does not perform automatic resizing or visibility changes.
    // Use the `processContentUpdates` parameter to adjust the size and visibility of your Banner according to your use case.
    processContentUpdates: { result in
      switch result {
      case .success(let updates):
        if let height = updates.height {
          // Adjust the visibility and/or height according to your parent controller.
        }
      case .failure(let error):
        // Handle the error.
      }
    }
  )
}

Java コードでバナーを取得するには、以下を使用します。

1
Banner globalBanner = Braze.getInstance(context).getBanner("global_banner");

次の XML を含めることで、Android ビューレイアウトでバナーを作成できます。

1
2
3
4
5
<com.braze.ui.banners.BannerView
    android:id="@+id/global_banner_id"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:placementId="global_banner" />

Android ビューを使用している場合は、次の XML を使用します。

1
2
3
4
5
<com.braze.ui.banners.BannerView
    android:id="@+id/global_banner_id"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:placementId="global_banner" />

Jetpack Compose を使用している場合は、次を使用できます。

1
Banner(placementId = "global_banner")

Kotlin でバナーを取得するには、以下を使用します。

1
val banner = Braze.getInstance(context).getBanner("global_banner")

React Native の新しいアーキテクチャを使用している場合は、BrazeBannerView をファブリックコンポーネントとして AppDelegate.mm に登録する必要があります。

1
2
3
4
5
6
7
8
#ifdef RCT_NEW_ARCH_ENABLED
/// Register the `BrazeBannerView` for use as a Fabric component.
- (NSDictionary<NSString *,Class<RCTComponentViewProtocol>> *)thirdPartyFabricComponents {
  NSMutableDictionary * dictionary = [super thirdPartyFabricComponents].mutableCopy;
  dictionary[@"BrazeBannerView"] = [BrazeBannerView class];
  return dictionary;
}
#endif

最もシンプルに統合するには、以下の JavaScript XML (JSX) スニペットをビュー階層に追加し、配置 ID だけを提供します。

1
2
3
<Braze.BrazeBannerView
  placementID='global_banner'
/>

React Native でバナーのデータモデルを取得したり、ユーザーのキャッシュにその配置があるかどうかをチェックするには、以下を使用します。

1
const banner = await Braze.getBanner("global_banner");
1
This feature is not currently supported on Unity.
1
This feature is not currently supported on Cordova.

最も簡単な統合のためには、以下のウィジェットをビュー階層に追加し、配置 IDだけを提供します。

1
2
3
4
BrazeBannerView(
  placementId: "global_banner",
),
To get the Banner's data model in Flutter, use:

getBanner メソッドを使えば、ユーザーのキャッシュにその配置があるかどうかをチェックできます。

1
2
3
4
5
6
7
braze.getBanner("global_banner").then((banner) {
  if (banner == null) {
    // Handle null cases.
  } else {
    print(banner.toString());
  }
});
1
This feature is not currently supported on Roku.

ステップ 5: テストバナーを送信する(オプション)

バナーキャンペーンを開始する前に、テストバナーを送信して統合を確認することができます。テストバナーは別のインメモリキャッシュに保存され、アプリを再起動した場合には保持されません。追加のセットアップは必要ありませんが、テストデバイスがテストを表示できるように、フォアグラウンドのプッシュ通知を受信できる必要があります。

ログのインプレッション

Brazeは、SDKメソッドを使ってバナーを挿入する際に表示されているバナーのインプレッションを自動的に記録する。だから、インプレッションを手動でトラッキングする必要はない。

クリックを記録する

バナーのクリックを記録する方法は、バナーの表示方法とクリック処理関数の配置場所によって異なる。

標準バナーの内容(自動)

デフォルトのSDKメソッドを使ってバナーを挿入している場合、そのバナーが標準のエディターコンポーネント(画像, 写真、ボタン、テキスト)を使用していれば、クリックは自動的にトラッキングされる。SDKはこれらの要素にクリックリスナーを添付する。追加のコードは不要だ。

カスタムコードブロック

もしあなたのバナーがBrazeダッシュボードのカスタムコードエディターブロックを使用している場合、そのカスタムHTML内からクリックをログに記録するには`<brazeBridge.logClick()SCRIPT>`タグを使用しなければならない。これは、SDKメソッドを使ってバナーをレンダリングする場合でも当てはまる。なぜなら、SDKはカスタムコード内の要素にリスナーを自動的に添付できないからだ。

1
2
3
<button onclick="brazeBridge.logClick()">
  Click me
</button>

完全な参照については、バナー用のカスタムコードとJavaScriptブリッジを参照のこと。バナーの内部HTMLと親Braze SDKの間で通信層を提供brazeBridgeする。

カスタムUI実装(ヘッドレス)

バナーのHTMLをレンダリングする代わりに、バナーのカスタムプロパティを使って完全にカスタムUIを構築する場合、アプリケーションコードからクリック(およびインプレッション)を手動で記録しなければならない。SDKがバナーをレンダリングしていないため、カスタムUI要素とのインタラクションを自動的にトラッキングする方法がない。

バナーオブジェクトに対してメソッドlogClick()を使用する。

寸法とサイズ

バナーの寸法とサイズについて知っておくべきことは以下の通りだ:

  • コンポーザーでは、さまざまなディメンションのバナーをプレビューできますが、その情報は保存されず、SDK に送信されません。
  • HTML は、レンダリングされるコンテナの全幅を使用します。
  • 固定ディメンションの要素を作成し、そのディメンションをコンポーザーでテストすることをお勧めします。

カスタムプロパティ

バナーキャンペーンのカスタムプロパティを使って、SDKを通じてキーと値のデータを取り出し、アプリの動作や外観を変更できる。例えば、次のようなことができる:

  • サードパーティの分析ツールや連携サービス向けにメタデータを送信する。
  • メタデータ(例:JSONtimestampオブジェクト)を使って条件分岐ロジックをトリガーする。
  • バナーの動作を、含まれるメタデータ(例:ratioや)に基づいてコントロールformatする。

前提条件

バナーキャンペーンにカスタムプロパティを追加する必要がある。さらに、カスタムプロパティにアクセスするために必要な最小限のSDKバージョンは以下の通りだ:

カスタムプロパティにアクセスする

バナーのカスタムプロパティにアクセスするには、ダッシュボードで定義されたプロパティの種類に基づいて、以下のいずれかの方法を使用する。キーがその型のプロパティと一致しない場合、またはキーが存在しない場合、メソッドはを返すnull

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Returns the Banner instance
const banner = braze.getBanner("placement_id_homepage_top");

// banner may be undefined or null
if (banner) {

  // Returns the string property
  const stringProperty = banner.getStringProperty("color");

  // Returns the boolean property
  const booleanProperty = banner.getBooleanProperty("expanded");

  // Returns the number property
  const numberProperty = banner.getNumberProperty("height");

  // Returns the timestamp property (as a number)
  const timestampProperty = banner.getTimestampProperty("account_start");

  // Returns the image URL property as a string of the URL
  const imageProperty = banner.getImageProperty("homepage_icon");

  // Returns the JSON object property
  const jsonObjectProperty = banner.getJsonProperty("footer_settings");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Passes the specified banner to the completion handler
AppDelegate.braze?.banners.getBanner(for: "placement_id_homepage_top") { banner in
  // Returns the string property
  let stringProperty: String? = banner.stringProperty(key: "color")

  // Returns the boolean property
  let booleanProperty: Bool? = banner.boolProperty(key: "expanded")

  // Returns the number property as a double
  let numberProperty: Double? = banner.numberProperty(key: "height")

  // Returns the Unix UTC millisecond timestamp property as an integer
  let timestampProperty: Int? = banner.timestampProperty(key: "account_start")

  // Returns the image property as a String of the image URL
  let imageProperty: String? = banner.imageProperty(key: "homepage_icon")

  // Returns the JSON object property as a [String: Any] dictionary
  let jsonObjectProperty: [String: Any]? = banner.jsonObjectProperty(key: "footer_settings")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Returns the Banner instance
Banner banner = Braze.getInstance(context).getBanner("placement_id_homepage_top");

// banner may be undefined or null
if (banner != null) {
  // Returns the string property
  String stringProperty = banner.getStringProperty("color");
  
  // Returns the boolean property
  Boolean booleanProperty = banner.getBooleanProperty("expanded");
  
  // Returns the number property
  Number numberProperty = banner.getNumberProperty("height");
  
  // Returns the timestamp property (as a Long)
  Long timestampProperty = banner.getTimestampProperty("account_start");
  
  // Returns the image URL property as a String of the URL
  String imageProperty = banner.getImageProperty("homepage_icon");
  
  // Returns the JSON object property as a JSONObject
  JSONObject jsonObjectProperty = banner.getJSONProperty("footer_settings");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Returns the Banner instance
val banner: Banner = Braze.getInstance(context).getBanner("placement_id_homepage_top") ?: return

// Returns the string property
val stringProperty: String? = banner.getStringProperty("color")

// Returns the boolean property
val booleanProperty: Boolean? = banner.getBooleanProperty("expanded")

// Returns the number property
val numberProperty: Number? = banner.getNumberProperty("height")

// Returns the timestamp property (as a Long)
val timestampProperty: Long? = banner.getTimestampProperty("account_start")

// Returns the image URL property as a String of the URL
val imageProperty: String? = banner.getImageProperty("homepage_icon")

// Returns the JSON object property as a JSONObject
val jsonObjectProperty: JSONObject? = banner.getJSONProperty("footer_settings")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Get the Banner instance
const banner = await Braze.getBanner('placement_id_homepage_top');
if (!banner) return;

// Get the string property
const stringProperty = banner.getStringProperty('color');

// Get the boolean property
const booleanProperty = banner.getBooleanProperty('expanded');

// Get the number property
const numberProperty = banner.getNumberProperty('height');

// Get the timestamp property (as a number)
const timestampProperty = banner.getTimestampProperty('account_start');

// Get the image URL property as a string
const imageProperty = banner.getImageProperty('homepage_icon');

// Get the JSON object property
const jsonObjectProperty = banner.getJSONProperty('footer_settings');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Fetch the banner asynchronously
_braze.getBanner(placementId).then(('placement_id_homepage_top') {
  // Get the string property
  final String? stringProperty = banner?.getStringProperty('color');
  
  // Get the boolean property
  final bool? booleanProperty = banner?.getBooleanProperty('expanded');
  
  // Get the number property
  final num? numberProperty = banner?.getNumberProperty('height');
  
  // Get the timestamp property
  final int? timestampProperty = banner?.getTimestampProperty('account_start');
  
  // Get the image URL property
  final String? imageProperty = banner?.getImageProperty('homepage_icon');
  
  // Get the JSON object propertyßß
  final Map<String, dynamic>? jsonObjectProperty = banner?.getJSONProperty('footer_settings');
  
  // Use these properties as needed in your UI or logic
});
New Stuff!