コンテンツにスキップ

分析の記録

Content Cards用のカスタムUIを構築する場合、インプレッション、クリック、非表示といった分析データを手動で記録する必要があります。これらはデフォルトのカードモデルでのみ自動的に処理されるためです。これらのイベントの記録は、Content Cards統合の標準的な部分であり、正確なキャンペーンレポートと請求に不可欠です。これを行うには、カスタムUIにBrazeのデータモデルからデータを入力し、その後手動でイベントを記録します。分析の記録方法を理解したら、Brazeの顧客がカスタムContent Cardsを作成する一般的な方法を確認できます。

分析のログ記録

カスタムContent Cardsを実装する際、Content Cardオブジェクトを解析して、title、cardDescription、imageUrlなどのペイロードデータを抽出できます。その後、取得したモデルデータを使用してカスタムUIを構築できます。

Content Cardsのデータモデルを取得するには、Content Cardsの更新を購読します。特に注意すべきプロパティが2つあります。

  • id:Content CardのID文字列を表します。カスタムContent Cardsから分析をログ記録するために使用される一意の識別子です。
  • extras:Brazeダッシュボードのすべてのキーと値のペアを含みます。

idとextras以外のすべてのプロパティは、カスタムContent Cardsの解析においてオプションです。データモデルの詳細については、各プラットフォームの統合記事を参照してください:Android、iOS、Web。

subscribeToContentCardsEvents()でコールバック関数を登録して、キャッシュされたカードの受信とカードの更新時の通知を取得します。

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

// - Available in version 7.0.0+
braze.subscribeToContentCardsEvents((event) => {
  switch (event.type) {
    case braze.ChannelEventType.CACHE_REPLAY:
    case braze.ChannelEventType.CACHE_LOAD:
    case braze.ChannelEventType.DATA_UPDATED: {
      const cards = event.cacheSnapshot.contentCards.cards;
      // For example:
      cards.forEach(card => {
        if (card.isControl) {
          // Do not display the control card, but remember to call `logContentCardImpressions([card])`
        }
        else if (card instanceof braze.ClassicCard || card instanceof braze.CaptionedImage) {
          // Use `card.title`, `card.imageUrl`, etc.
        }
        else if (card instanceof braze.ImageOnly) {
          // Use `card.imageUrl`, etc.
        }
      });
      break;
    }
    case braze.ChannelEventType.ERROR:
      // Check `event.reason` and `event.retryState`
      break;
  }
});

braze.subscribeToContentCardsUpdates((updates) => {
  const cards = updates.cards;
// For example:
  cards.forEach(card => {
    if (card.isControl) {
      // Do not display the control card, but remember to call `logContentCardImpressions([card])`
    }
    else if (card instanceof braze.ClassicCard || card instanceof braze.CaptionedImage) {
      // Use `card.title`, `card.imageUrl`, etc.
    }
    else if (card instanceof braze.ImageOnly) {
      // Use `card.imageUrl`, etc.
    }
  })
});

braze.openSession();

Web SDK 7.0.0以降ではsubscribeToContentCardsEventsを使用してください。subscribeToContentCardsUpdatesは以前のパターンで、7.0.0で非推奨になりました。

受信できるイベントの完全なリストについては、Content Cardsの作成を参照してください。

ステップ1:プライベートサブスクライバー変数を作成する

カードイベントを購読するには、まずカスタムクラスにサブスクライバーを保持するプライベート変数を宣言します。

// - Available in version 44.0.0+
private IEventSubscriber<ContentCardsEvent> mContentCardsEventSubscriber;

private IEventSubscriber<ContentCardsUpdatedEvent> mContentCardsUpdatedSubscriber;

ステップ2:イベントを購読する

次に、以下のコードを追加してBrazeからContent Cardsイベントを購読します。通常、カスタムContent CardsアクティビティのActivity.onCreate()内で行います。

// - Available in version 44.0.0+
// Remove the previous subscriber before rebuilding a new one with our new activity.
Braze.getInstance(context).removeSingleSubscription(mContentCardsEventSubscriber, ContentCardsEvent.class);
mContentCardsEventSubscriber = new IEventSubscriber<ContentCardsEvent>() {
    @Override
    public void trigger(ContentCardsEvent event) {
        if (event instanceof ContentCardsEvent.CacheReplay) {
            handleCards(((ContentCardsEvent.CacheReplay) event).getCacheSnapshot());
        } else if (event instanceof ContentCardsEvent.CacheLoad) {
            handleCards(((ContentCardsEvent.CacheLoad) event).getCacheSnapshot());
        } else if (event instanceof ContentCardsEvent.DataUpdated) {
            handleCards(((ContentCardsEvent.DataUpdated) event).getCacheSnapshot());
        }
    }
};
Braze.getInstance(context).subscribeToContentCardsEvents(mContentCardsEventSubscriber);
Braze.getInstance(context).requestContentCardsRefresh();

// Remove the previous subscriber before rebuilding a new one with our new activity.
Braze.getInstance(context).removeSingleSubscription(mContentCardsUpdatedSubscriber, ContentCardsUpdatedEvent.class);
mContentCardsUpdatedSubscriber = new IEventSubscriber<ContentCardsUpdatedEvent>() {
    @Override
    public void trigger(ContentCardsUpdatedEvent event) {
        List<Card> allCards = event.getAllCards();
    }
};
Braze.getInstance(context).subscribeToContentCardsUpdates(mContentCardsUpdatedSubscriber);
Braze.getInstance(context).requestContentCardsRefresh();

private void handleCards(ContentCardsCacheSnapshot cacheSnapshot) {
    List<Card> allCards = cacheSnapshot.getCards();
}

ステップ3:購読を解除する

カスタムアクティビティが画面から離れる際に、購読を解除することも推奨します。アクティビティのonDestroy()ライフサイクルメソッドに以下のコードを追加してください。

// - Available in version 44.0.0+
Braze.getInstance(context).removeSingleSubscription(mContentCardsEventSubscriber, ContentCardsEvent.class);

Braze.getInstance(context).removeSingleSubscription(mContentCardsUpdatedSubscriber, ContentCardsUpdatedEvent.class);

ステップ1:プライベートサブスクライバー変数を作成する

カードイベントを購読するには、まずカスタムクラスにサブスクライバーを保持するプライベート変数を宣言します。

// - Available in version 44.0.0+
private var contentCardsEventSubscriber: IEventSubscriber<ContentCardsEvent>? = null

private var contentCardsUpdatedSubscriber: IEventSubscriber<ContentCardsUpdatedEvent>? = null

ステップ2:イベントを購読する

次に、以下のコードを追加してBrazeからContent Cardsイベントを購読します。通常、カスタムContent CardsアクティビティのActivity.onCreate()内で行います。

// - Available in version 44.0.0+
// Remove the previous subscriber before rebuilding a new one with our new activity.
Braze.getInstance(context).removeSingleSubscription(contentCardsEventSubscriber, ContentCardsEvent::class.java)
contentCardsEventSubscriber = IEventSubscriber { event ->
    when (event) {
        is ContentCardsEvent.CacheReplay -> handleCards(event.cacheSnapshot)
        is ContentCardsEvent.CacheLoad -> handleCards(event.cacheSnapshot)
        is ContentCardsEvent.DataUpdated -> handleCards(event.cacheSnapshot)
        else -> {}
    }
}
Braze.getInstance(context).subscribeToContentCardsEvents(contentCardsEventSubscriber)
Braze.getInstance(context).requestContentCardsRefresh()

// Remove the previous subscriber before rebuilding a new one with our new activity.
Braze.getInstance(context).removeSingleSubscription(contentCardsUpdatedSubscriber, ContentCardsUpdatedEvent::class.java)
contentCardsUpdatedSubscriber = IEventSubscriber { event ->
    val allCards = event.allCards
}
Braze.getInstance(context).subscribeToContentCardsUpdates(contentCardsUpdatedSubscriber)
Braze.getInstance(context).requestContentCardsRefresh()

private fun handleCards(cacheSnapshot: ContentCardsCacheSnapshot) {
    val allCards = cacheSnapshot.cards
}

ステップ3:購読を解除する

カスタムアクティビティが画面から離れる際に、購読を解除することも推奨します。アクティビティのonDestroy()ライフサイクルメソッドに以下のコードを追加してください。

// - Available in version 44.0.0+
Braze.getInstance(context).removeSingleSubscription(contentCardsEventSubscriber, ContentCardsEvent::class.java)

Braze.getInstance(context).removeSingleSubscription(contentCardsUpdatedSubscriber, ContentCardsUpdatedEvent::class.java)

各イベントが発生するタイミングと、各更新理由、リトライ状態、分析アクション、エラー理由の意味については、イベント購読を参照してください。

Android SDK 44.0.0以降ではsubscribeToContentCardsEventsを使用してください。subscribeToContentCardsUpdatesは以前のパターンで、44.0.0で非推奨になりました。

Content Cardsのデータモデルにアクセスするには、brazeインスタンスでcontentCards.cardsを呼び出します。

let cards: [Braze.ContentCard] = AppDelegate.braze?.contentCards.cards

さらに、Content Cardsイベントを購読して、キャッシュの変更、分析、エラーを監視することもできます。以下の2つの方法があります。

  1. キャンセル可能オブジェクトを保持する方法
  2. AsyncStreamを保持する方法

キャンセル可能オブジェクト

// - Available in version 19.0.0+
// This subscription is maintained through a Braze cancellable, which will observe for events until the subscription is cancelled.
// You must keep a strong reference to the cancellable to keep the subscription active.
// The subscription is canceled either when the cancellable is deinitialized or when you call its `.cancel()` method.
let cancellable = AppDelegate.braze?.contentCards.subscribeToEvents { [weak self] event in
  switch event {
  case .cacheReplay(let cacheSnapshot):
    // Initial cache snapshot, delivered immediately after subscribing
    break
  case .cacheLoad(let cacheSnapshot):
    // Cache loaded at the start of a user session (for example, after `changeUser()`)
    break
  case .dataUpdated(let cacheSnapshot, let reason):
    // Cache changed after the initial replay
    break
  case .impressionEvent(let card, let action):
    break
  case .clickEvent(let card, let action):
    break
  case .dismissEvent(let card, let action):
    break
  case .error(let reason, let retryState):
    break
  }
}

let cancellable = AppDelegate.braze?.contentCards.subscribeToUpdates { [weak self] contentCards in
  // Implement your completion handler to respond to updates in `contentCards`.
}

AsyncStream

// - Available in version 19.0.0+
Task {
  for await event in AppDelegate.braze?.contentCards.eventsStream ?? AsyncStream { _ in } {
    // Same switch statement as the cancellable example above.
  }
}

let stream: AsyncStream<[Braze.ContentCard]> = AppDelegate.braze?.contentCards.cardsStream

Swift SDK 19.0.0以降ではsubscribeToEvents(_:)またはeventsStreamを使用してください。subscribeToUpdates(_:)とcardsStreamは以前のパターンで、19.0.0で非推奨になりました。

各イベントが発生するタイミングと、各更新理由、リトライ状態、分析アクション、エラー理由の意味については、イベント購読を参照してください。

ノンブロッキングスナップショットアクセサー

以下のメソッドを使用して、呼び出しスレッドをブロックせずに現在のキャッシュ状態を読み取ります。各コンプリーションハンドラーは常にメインスレッドで配信されます。

// All cached cards.
AppDelegate.braze?.contentCards.getCachedContentCards { cards in
  // Use `cards` here.
}

// Unviewed cards only (excludes control cards).
AppDelegate.braze?.contentCards.getUnviewedCards { cards in
  // Use `cards` here.
}

// Date of the last server sync for the current user (nil until the first sync completes).
AppDelegate.braze?.contentCards.getLastUpdate { date in
  // Use `date` here.
}
NSArray<BRZContentCardRaw *> *contentCards = AppDelegate.braze.contentCards.cards;

さらに、Content Cardsイベントを購読したい場合は、subscribeToEvents:を呼び出すことができます。各イベントタイプはそれぞれのクラスにブリッジされます(例:BRZContentCardsDataUpdatedEvent)。isKindOfClass:で判別できます。初期キャッシュリプレイとその後のデータ更新は、どちらもBRZContentCardsDataUpdatedEventにブリッジされます。区別するにはreasonをBRZContentCardsDataUpdatedEvent.cacheReplayReasonと比較してください。

// - Available in version 19.0.0+
// This subscription is maintained through a Braze cancellable, which will continue to observe for events until the subscription is cancelled.
BRZCancellable *cancellable = [self.braze.contentCards subscribeToEvents:^(BRZContentCardsEvent *event) {
  if ([event isKindOfClass:[BRZContentCardsDataUpdatedEvent class]]) {
    BRZContentCardsDataUpdatedEvent *updated = (BRZContentCardsDataUpdatedEvent *)event;
    if (updated.reason == BRZContentCardsDataUpdatedEvent.cacheReplayReason) {
      // Initial cache snapshot, delivered immediately after subscribing
    } else {
      // Cache changed after the initial replay
    }
  } else if ([event isKindOfClass:[BRZContentCardsCacheLoadEvent class]]) {
    // Cache loaded at the start of a user session (for example, after `changeUser()`)
  }
}];

BRZCancellable *cancellable = [self.braze.contentCards subscribeToUpdates:^(NSArray<BRZContentCardRaw *> *contentCards) {
  // Implement your completion handler to respond to updates in `contentCards`.
}];

Swift SDK 19.0.0以降ではsubscribeToEvents:を使用してください。subscribeToUpdates:は以前のパターンで、19.0.0で非推奨になりました。

呼び出しスレッドをブロックせずに現在のキャッシュ状態を読み取るには、以下のメソッドを使用してください。各コンプリーションハンドラーはメインスレッドで配信されます。

// All cached cards.
[AppDelegate.braze.contentCards getCachedContentCardsWithCompletion:^(NSArray<BRZContentCardRaw *> *cards) {
  // Use `cards` here.
}];

// Unviewed cards only (excludes control cards).
[AppDelegate.braze.contentCards getUnviewedCardsWithCompletion:^(NSArray<BRZContentCardRaw *> *cards) {
  // Use `cards` here.
}];

// Date of the last server sync for the current user (nil until the first sync completes).
[AppDelegate.braze.contentCards getLastUpdateWithCompletion:^(NSDate * _Nullable date) {
  // Use `date` here.
}];

更新をリッスンするには、Content Cardsの更新イベントを購読します。

const subscription = Braze.addListener(Braze.Events.CONTENT_CARDS_UPDATED, (update) => {
  const cards = update.cards;
  cards.forEach(card => {
    if (card.isControl) {
      // Do not display the control card, but remember to log an impression
    } else {
      // Use card.title, card.cardDescription, card.image, etc.
    }
  });
});

最新のキャッシュされたContent Cardsデータを取得するには:

import Braze from "@braze/react-native-sdk";

const cachedCards = await Braze.getCachedContentCards();

BrazeサーバーからContent Cardsの手動更新をリクエストするには:

Braze.requestContentCardsRefresh();

イベントのログ記録

インプレッション、クリック、非表示などの重要な指標のログ記録は、すばやく簡単に行えます。カスタムクリックリスナーを設定して、これらの分析を手動で処理できます。

ユーザーがカードを閲覧したときに、logContentCardImpressionsを使用してインプレッションイベントを記録します。

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

braze.logContentCardImpressions([card1, card2, card3]);

ユーザーがカードを操作したときに、logContentCardClickを使用してカードクリックイベントを記録します。

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

braze.logContentCardClick(card);

BrazeManagerは、Content Cardsオブジェクトの配列リストなどのBraze SDKの依存関係を参照して、Cardを取得し、Brazeのログ記録メソッドを呼び出すことができます。ContentCardable基底クラスを使用して、BrazeManagerにデータを簡単に参照・提供できます。

カードのインプレッションまたはクリックを記録するには、それぞれCard.logClick()またはCard.logImpression()を呼び出します。

特定のカードに対して、Content Cardsを手動で「非表示」としてログ記録またはBrazeに設定するには、isDismissedを使用します。カードがすでに非表示としてマークされている場合、再度非表示としてマークすることはできません。

カスタムクリックリスナーを作成するには、IContentCardsActionListenerを実装するクラスを作成し、BrazeContentCardsManagerに登録します。onContentCardClicked()メソッドを実装します。これは、ユーザーがContent Cardsをクリックしたときに呼び出されます。次に、BrazeにContent Cardsのクリックリスナーを使用するよう指示します。

例:

BrazeContentCardsManager.getInstance().setContentCardsActionListener(new IContentCardsActionListener() {
  @Override
  public boolean onContentCardClicked(Context context, Card card, IAction cardAction) {
    return false;
  }

  @Override
  public void onContentCardDismissed(Context context, Card card) {

  }
});

例:

BrazeContentCardsManager.getInstance().contentCardsActionListener = object : IContentCardsActionListener {
  override fun onContentCardClicked(context: Context, card: Card, cardAction: IAction): Boolean {
    return false
  }

  override fun onContentCardDismissed(context: Context, card: Card) {

  }
}

BrazeContentCardUIViewControllerDelegateプロトコルを実装し、デリゲートオブジェクトをBrazeContentCardUI.ViewControllerのdelegateプロパティとして設定します。このデリゲートは、カスタムオブジェクトのデータをBrazeに渡してログ記録する処理を行います。例については、Content Cards UIチュートリアルを参照してください。

// Set the delegate when creating the Content Cards controller
contentCardsController.delegate = delegate

// Method to implement in delegate
func contentCard(
    _ controller: BrazeContentCardUI.ViewController,
    shouldProcess clickAction: Braze.ContentCard.ClickAction,
    card: Braze.ContentCard
  ) -> Bool {
  // Intercept the content card click action here.
  return true
}
// Set the delegate when creating the Content Cards controller
contentCardsController.delegate = delegate;

// Method to implement in delegate
- (BOOL)contentCardController:(BRZContentCardUIViewController *)controller
                shouldProcess:(NSURL *)url
                         card:(BRZContentCardRaw *)card {
  // Intercept the content card click action here.
  return YES;
}

ユーザーがカードを閲覧したときに、インプレッションイベントを記録します。

Braze.logContentCardImpression(card.id);

ユーザーがカードを操作したときに、カードクリックイベントを記録します。

Braze.logContentCardClicked(card.id);

ユーザーがカードを非表示にしたときに、非表示イベントを記録します。

Braze.logContentCardDismissed(card.id);

クリック時の動作の処理

カスタムフィードでユーザーがContent Cardsをクリックした場合、クリック時の動作(URLへの遷移、ディープリンク、カスタムイベントのログ記録など)は自動的には処理されません。handleBrazeActionを使用して、カードのURLを処理し、Brazeアクション(brazeActions:// URL)を含む、設定済みのクリック時アクションを実行します。

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

// In your card click handler
function onCardClick(card) {
  // Log the click
  braze.logContentCardClick(card);

  // Handle the on-click behavior
  if (card.url) {
    braze.handleBrazeAction(card.url);
  }
}
パラメーター 説明
url 有効なURL、またはbrazeActions://スキームを使用した有効なBrazeアクションURL。
openLinkInNewTab (オプション)URLを新しいタブで開くかどうか。デフォルトはfalseです。

クリック時の動作は、デフォルトのContent Cards UIによって自動的に処理されます。カスタム実装の場合は、分析のログ記録で説明されているIContentCardsActionListenerインターフェイスを使用します。

クリック時の動作は、デフォルトのContent Cards UIによって自動的に処理されます。カスタム実装の場合は、分析のログ記録で説明されているBrazeContentCardUIViewControllerDelegateプロトコルを使用します。

カスタムフィードでユーザーがContent Cardsをクリックした場合、クリック時の動作は自動的には処理されません。Braze.logContentCardClicked(cardId)でクリックをログ記録した後、Braze.processContentCardClickAction(cardId)を呼び出して、ディープリンク、URL、およびbrazeActions://アクションを処理します。メソッドリファレンスについては、React Native Content Cardsを参照してください。

import Braze from "@braze/react-native-sdk";

function onCardPress(card) {
  Braze.logContentCardClicked(card.id);

  if (card.url) {
    Braze.processContentCardClickAction(card.id);
  }
}

ユニーク非表示数がユニークインプレッション数を上回る場合

ユニーク非表示数がユニークインプレッション数を上回っている場合、カスタムContent Cardsの統合で、該当するカードのインプレッションを記録せずに非表示を記録しています。BrazeのデフォルトのContent Cards UIは両方を自動的に記録するため、この不一致はカスタムUIを使用している場合にのみ発生します。

カードを表示するたびにインプレッションを記録し、ユーザーがカードを非表示にしたときに非表示を記録してください。メソッド名と例については、以下のプラットフォームセクションを参照してください。

Content Cardsの分析が欠落している場合

Content Cardsがアプリに正しく表示されているにもかかわらず、分析データ(インプレッション、クリックなど)が一貫して受信されない場合、SDKの統合に問題がある可能性があります。

  • カスタムContent Cardsビュー(Android、iOS、Web): デフォルトのBraze UIは、すべてのプラットフォームでインプレッションとクリックを自動的に記録します。カスタムContent Cardsビューまたは実装を使用している場合は、アプリケーション内で適切なログ記録メソッドを明示的に呼び出す必要があります。お使いのプラットフォームの分析の記録を参照してください。特にカスタムWeb実装の場合は、Braze Web SDKが読み込まれていることを確認し、ブラウザーコンソールでエラーを確認し、カードデータが受信されていることを検証してください。
  • SDKの初期化とユーザー識別: カードを表示する前に、SDKが完全に初期化されていることを確認してください。SDKが未初期化、遅延初期化モード、またはGDPR無効の状態では、イベントはキューに入れられずにサイレントに破棄されます。SDKは匿名ユーザーの分析も記録しますが、「ユニークデイリーインプレッション」などのダッシュボード指標にはユーザーIDの解決が必要です。そのため、可能な限りカードを表示する前にchangeUserを呼び出してください。

コンテンツカードID

キャンペーンが受信者に送信されるたびに、新しいコンテンツカードIDが生成されます。同じユーザーが後の送信で再度そのキャンペーンを受信した場合、Brazeは新しいIDを割り当てます。カスタム実装でインプレッション、クリック、非表示を記録する際は、カードのidを参照してください。

New Stuff!