Skip to content
Last updated

リアルタイムパーソナライゼーション2.0クライアントサイドユースケースガイド

はじめにと概要

リアルタイムパーソナライゼーション2.0(クライアントサイド)は、Webおよびマーケティングチームがブラウザから直接、即座に高度にカスタマイズされた体験を提供できるようにします。この最新のデータエンジンにより、WebサイトやCMSは、最新の顧客プロファイル属性、行動、オーディエンスセグメントメンバーシップを即座に反映して、各訪問者に対してコンテンツを動的にパーソナライズできます。

従来のサーバーサイドパーソナライゼーション(すべてのリクエストを中間バックエンドを経由させる)とは異なり、クライアントサイドのリアルタイムパーソナライゼーション2.0では、ユーザーのブラウザで実行されるJavaScriptがTreasure DataのAPIからパーソナライゼーションペイロードを安全に取得できるため、追加のネットワークホップが不要になり、レイテンシが削減されます。このアプローチにより、迅速なUI更新が可能になり、ユーザーがサイトに着陸したり操作したりするとすぐに、ターゲットオファー、商品推奨、ロイヤルティバナーなどを表示するといった強力なページ内パーソナライゼーションシナリオが実現します。

クライアントサイド版では、すべてのAPI呼び出しはWebブラウザから発信され、パブリックトークンを使用してCORS対応エンドポイントから提供されます。機密性のない(非PII)データのみがフロントエンドに配信されるように組み込みのセーフガードが備わっています。このガイドは、ブラウザベースの統合に特化しており、トークン設定、属性の機密性制御、UI設定、プライバシーとコンプライアンスのベストプラクティスなどを含め、クライアントサイドパーソナライゼーションを安全に有効にするための明確なステップバイステップの手順を提供します。

サーバーサイド統合については別のドキュメントもご覧いただけますが、このガイドは、ブラウザで直接リアルタイムパーソナライゼーションを実現したい開発者、データエンジニア、マーケター向けに設計されており、Web上での最新のコマース、コンテンツ、エンゲージメント体験をサポートします。

このステップバイステップガイドを通じて、イベント追跡と属性設定からオーディエンスセグメンテーション、パーソナライゼーション設計、安全なページ内統合まで、Webアプリケーションでクライアントサイドのリアルタイムパーソナライゼーション2.0ユースケースを構築および実装する方法を学習します。

ステップ1: データ取り込みとAPIオプション(クライアントサイド)

クライアントサイドのリアルタイムパーソナライゼーションにより、Webアプリケーションはユーザーのブラウザから直接、完全に動的でパーソナライズされた体験を提供できます。このセクションでは、プライバシー、コンプライアンス、データアーキテクチャのベストプラクティスを維持しながら、ブラウザJavaScriptからTreasure Dataのプラットフォームにイベントデータを安全かつ効果的に送信し、リアルタイムオーディエンス評価とパーソナライズされたペイロード配信を行う方法について説明します。

クライアント統合パーソナライゼーションのデータフローとイベント取り込み

クライアントサイドセットアップでは、ページビュー、クリック、サインアップ、商品インタラクションなどのイベントは、サイト上で実行されるブラウザJavaScriptによってキャプチャされます。これらのイベントは、安全なCORS対応エンドポイントを介してTreasure DataのパーソナライゼーションAPIに直接送信されます。中間サーバーは不要で、レイテンシを最小限に抑え、Webパーソナライゼーションユースケースの「即座の」UI更新を実現します。

  • イベント例: ページビュー、アイテムクリック、カート追加、コンバージョン、カスタムエンゲージメントマイルストーン。

  • 典型的なワークフロー:

    • カスタムJavaScript、タグマネージャー、またはTDのJS SDK(M2用に更新後)を使用して関連イベントをキャプチャします。

    • 各イベントを関連する識別子(例: 匿名ID、td_client_id)、コンテキスト(URL、パス)、パーソナライゼーションに必要な非機密属性とともにパッケージ化します。

安全なデータ送信: ブラウザでは非機密データのみ

機密性のあるPIIまたは機密のビジネスロジックをブラウザから直接送信しないでください。

クライアントサイドで送信されるすべてのイベントデータは、厳密に非機密である必要があります。機密データの場合は、代わりにサーバーサイドの取り込みパスを使用してください。

  • 安全なフィールド: 匿名ユーザーID、高レベルの行動(例: td_path、商品カテゴリ)

  • 安全でないフィールド: メールアドレス、電話番号、生の個人識別子、または機密のビジネスロジック

適切なAPIの選択: パーソナライゼーションAPI vs 取り込みAPI

主なイベント取り込み方法は2つあります:

  1. パーソナライゼーションAPI(クライアントサイドフォーカス)

    • ユースケース:

      • イベントを送信し、ブラウザからの単一のHTTP POSTリクエストで即座にパーソナライゼーションオファーを受け取ります。

      • ページロードまたはユーザーインタラクション時のリアルタイムで動的なコンテンツ更新に使用されます。

    • レスポンス:

      • 非機密属性/セグメントのみが含まれます。オファーに機密データ(設定での属性の機密性による)が含まれている場合、レスポンスでは{}に置き換えられます。
    • エンドポイント:

      • パブリックCORS対応URL(例: /public/{db}/{table})

      • WP13n-Tokenヘッダーにパブリックタイプのトークンが必要です。

    • セキュリティ上の考慮事項:

      • ブラウザコードではパブリックトークンのみを使用してください。これらにはIPホワイトリストがなく、サービスレベルで「パブリック」として作成する必要があります。プライベートトークンはブラウザログにエラーを生成し、オファーを返しません。
  2. 取り込みAPI

    • ユースケース:

      • バックエンド/サーバー経由でイベントを送信して保存し、後でセグメンテーションを行います。

      • パーソナライゼーションペイロードを返しません。

    • 使用するタイミング: ブラウザを経由すべきでない機密または規制されたデータの場合、またはバッチ分析用の生ログをキャプチャする場合。

APIリクエストと例

クライアントサイドの「fetch」例(将来のJS SDKサポートを想定、またはwindow.fetchで使用):

fetch('https://us01.p13n.in.treasuredata.com/public/<YOUR_DB>/<YOUR_TABLE>', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.treasuredata.v1+json',
    'WP13n-Token': '<ACCOUNT_ID>/<REACTOR_ID>/<PUBLIC_TOKEN>',
    'Authorization':'TD1 <WRITE API KEY>'
  },
  body: JSON.stringify({
    td_client_id: '1234-5678-9012-3456',
    td_url: window.location.href,
    td_path: window.location.pathname,
    // ... 追加の非機密イベントフィールド
    })
  })
  .then(res => res.json())
  .then(data => {
    // data.offers: パーソナライズされたセクション
  }
);

注意:

  • 含めないでください: いかなる理由でもブラウザサイドリクエストにプライベートトークンを使用しないでください。

  • 検証: トークンはパブリックである必要があり、オリジンが許可されている必要があり、レスポンスでは非機密データのみが返されます。

CORSとセキュリティ制御

  • APIエンドポイントは、Originヘッダーとトークンのパブリック/プライベートステータスの両方を検証します。

    • 有効なパブリックトークンと有効なOriginの場合、APIはCORSヘッダーとオファーペイロードで応答します。

    • 無効なトークン、プライベートトークン、または無効なOriginの場合、レスポンスは4xxでCORSヘッダーは送信されません。

  • クライアントサイドエンドポイントはパブリックトークンのみをサポートします。ブラウザからプライベートトークンを使用しようとすると失敗します。

セグメントとテーブルマッピング

  • クライアントサイドセットアップと同様に、各行動イベントは、リアルタイムオーディエンスロジックのための下流の「ペアレントセグメント」をサポートする明確で個別のテーブルにマップする必要があります。

  • ペアレントセグメントとテーブル定義は、TD ConsoleのUI内で事前に設定する必要があります。

  • クライアントサイドイベントのすべてのマッピング、更新、イベント設定はUI内で管理されます。標準統合にはバックエンドは必要ありません。

ベストプラクティスチェックリスト

  • ブラウザJavaScriptから非機密データのみを公開する

  • 常にCORS対応のパブリックエンドポイントとパブリックトークンを使用する

  • 各行動イベントタイプを明確なオーディエンスセグメンテーションのための適切なテーブルにマップする

  • プライバシー、ルール、またはアクセス制御が必要なデータの場合: ブラウザではなく、サーバーサイドの取り込みを使用する

要約表: クライアントサイドデータ取り込みの比較

オプションソースパーソナライゼーションレスポンストークンタイプエンドポイントパスユースケース
パーソナライゼーションAPIブラウザJSはい(リアルタイム)パブリックのみ/public/db/tableリアルタイムブラウザUXパーソナライゼーション
取り込みAPIバックエンドいいえ(保存のみ)プライベート/records機密、サーバーログ、コンプライアンスデータ

ステップ2: UIでのリアルタイムパーソナライゼーション設定(クライアントサイド)

Treasure DataのUIでクライアントサイドのリアルタイムパーソナライゼーション2.0を設定する際には、ブラウザのセキュリティ、プライバシーコンプライアンス、堅牢なガバナンス、そしてシームレスなエンドツーエンドの有効化を確保するための固有の要件とワークフローがあります。このセクションでは、クライアントサイドのパーソナライゼーションを作成・管理するためのユーザー体験とシステム上の制約を一通り説明します。

クライアントサイドパーソナライゼーション機能の有効化

  • クライアントサイド(ブラウザベース)の統合を有効にするには、アカウントでリアルタイムパーソナライゼーション2.0のグローバル機能フラグとM2クライアントサイドの機能フラグがいずれも有効化されている必要があります(例: サービス/トークン用の eng-lc-realtime-personalization-m2-1 と、属性レベルのPII機密性設定用の eng-lc-realtime-personalization-m2-2)。これらのフラグが有効になっていない場合、パブリックサービスや機密属性の指定に関するUIオプションは表示されません。

ワークフロー: パブリックなパーソナライゼーションサービスの作成

  1. ペアレントセグメントを作成

    • Audience Studioでペアレントセグメントを作成または選択します。このセグメントがパーソナライゼーションロジックの基礎になります。
  2. 新しいパーソナライゼーションサービスを作成(クライアントサイド向けのパブリック)

    • セグメントの「Personalization Configuration」に移動します。
    • 「Create new personalized service」をクリックします。
    • モーダルで「Service Type」を選択します。
      • クライアントサイドで利用する場合は Public(publishing)
      • サーバーサイド専用の場合は Private
    • 重要: 作成後にサービス種別(パブリック/プライベート)を変更することはできません。想定する連携パターンに合わせて慎重に選択してください。
  3. 名前、説明、検証

    • 一意の名前(最大100文字)と、必要に応じて説明を入力します。
    • 重複した名前や文字数制限を超えた名前は、「Name has already been taken」「Name is too long (maximum is 100 characters)」などのUI検証エラーになります。
    • 必須項目が未入力の場合は、UIが作成をブロックし、エラー表示が行われます。
  4. トークンの追加

    • パブリックサービスを作成したら、ブラウザで使用するトークンを1つ以上追加します。
    • 各トークンにも一意の名前(同様の検証あり)が必要です。
    • パブリックサービスとトークンの制約:
      • Allowed IPs(IP制限)は設定できません。設定しようとすると「Allowed ips must not be set when the parent service is public」という検証エラーが表示されます。
      • これらのトークンはクライアントのJavaScriptに安全に埋め込めます。
    • プライベートサービスの場合はIPホワイトリストを設定できます。
  5. トークンの形式と上限

    • APIトークンの形式は [ACCOUNT_INSTANCE_ID]/[REACTOR_INSTANCE_ID]/[RT_PERSONALIZATION_TOKEN] です。
    • 制限: サービスあたり最大50トークン、ペアレントセグメントあたり最大200トークン。

セキュリティ、不可変性、ガバナンス

  • ブラウザで使用できるのはパブリックトークンのみです。プライベートトークンはバックエンド/サーバー用途に限定されます。
  • 一度作成したサービスのパブリック/プライベート種別は変更できません。
  • 編集モーダルではサービス種別のフィールドは無効化され、変更できないようになっています。
  • これらの制約に反する操作を行うと、UIやAPIが明示的なエラーメッセージを返します。

トークン管理とUIの詳細

  • 各パブリックサービスのトークンはサイドパネルで管理します。
  • 上限の範囲内であればトークンを削除して再作成できます。
  • ユーザーセッションが失効している場合、トークン表示時にパスワードやSAML/SSOで再認証するプロンプトが表示されます。

機能フラグと権限による制御

  • パブリックサービスの作成/閲覧/編集や属性を機密として指定する操作は、機能フラグの展開状況とアカウント/ユーザーの権限に依存します。
  • 権限が不足しているユーザーには「You do not have permission to perform this action.」といった説明的なエラーが表示され、操作はブロックされます。

バリデーション、エラー処理、UIアシスト

  • UIはすべてのフィールドでリアルタイム検証を行い、空欄や重複、文字数超過を防ぎ、失敗時には明確なフィードバックを表示します。
  • システム仕様に反する操作を試みると、対応するエラーメッセージが返されます。
  • インポートおよび属性管理については、次の「イベントと属性の定義」セクションで、属性ごとの機密度設定や追加のコンプライアンス制御を参照してください。

まとめ表: クライアントサイド設定におけるUIの動作

タスクパブリックサービス/トークンプライベートサービス/トークン
サービス種別の編集可否不可不可
Allowed IPs(トークン)設定不可設定可
トークンの利用先ブラウザJSのみバックエンド/サーバーのみ
トークンの削除/追加制限内で可能制限内で可能
サービスあたりの最大トークン数5050
名前/説明のバリデーションありあり
セッション失効時の挙動SSO/パスワード再認証SSO/パスワード再認証

ベストプラクティス

  • パブリック(クライアント)とプライベート(サーバー)のサービスやトークンを識別できるよう、明確な命名規則を使用します。
  • 同じトークンやサービスを両方の環境で使い回さないでください。厳密に分離することで運用上の事故を防げます。
  • これらの設定が変更不可である点をチームや連携先に共有し、導入やロールアウト時のトラブルを避けてください。
  • UIに組み込まれた検証機能を活用し、設定ミスを防止してください。

ステップ3: イベントと属性の定義(クライアントサイド)

クライアントサイドのリアルタイムパーソナライゼーションサービスを設定したら、次はブラウザで取得するイベントを定義し、ページ内パーソナライゼーションを駆動するリアルタイム属性を構成します。サーバーサイドの方法と概念的には似ていますが、非機密データのみを扱えるようプライバシー、UI、ガバナンス面でより厳格な制御が組み込まれています。

イベントテーブルとイベント定義

リアルタイム構成セクションでは、WebサイトやWebアプリから送信される行動イベントを表すテーブルを選択または登録します。クライアントサイドパーソナライゼーションで一般的なイベント例は次のとおりです。

  • ページビュー(例: ホーム、カテゴリ、商品ページ)
  • クリック(商品詳細、カート投入、バナー)
  • Webサイトでのサインアップやログイン(PIIを含まない場合)
  • カスタムアクション(例: 動画完了、アセットのダウンロード)

新しいイベントを定義するには:

  • 設定UIのEvents領域で「Create new event」をクリックします。
  • そのイベントストリームを保存するデータテーブルを選択します。
  • 下流で参照しやすいよう、イベントにわかりやすい名前(例: product_page_view)を付けます。
  • (任意)URLパスやクエリなどでフィルタを設定し(例: td_path の正規表現 ^/retail/.*/product/.*)、特定のイベントだけをパーソナライゼーション対象にすることもできます。

ベストプラクティス:

  • イベントタイプごとにテーブルを分けて整理し、オーディエンスセグメントを細かく把握しやすくします。
  • バッチテーブルをリアルタイムに再利用する場合は、ブラウザから機密識別子が送信されないよう十分に確認してください。

機密度を考慮した属性の定義

クライアントサイド製品で重要なのは、Single、List、Imported属性の機密度を作成時(または編集時)に明示的に指定する必要がある点です。ブラウザ向けAPIのレスポンスでは、非機密の属性だけが返却されます。

属性タイプ

  • Single: 訪問者ごとの最新値(文字列または数値)を保持します。最後に閲覧した商品、現在のページ、直近のカテゴリなどの追跡に便利です。PIIを露出しない場合にのみ非機密としてマークしてください(メールアドレスや電話番号などは避けること)。
  • List: 訪問者ごとに最大100件の配列を保持します(例: 最近閲覧した商品やカテゴリ)。各アイテムは60日で期限切れになります。リスト内に機密データが含まれる場合は属性全体を機密として指定し、それ以外は非機密にします。
  • Counter: イベントの発生回数をカウントします(例: page_views_last_7_days)。カウンターは常に非機密とみなされ、UIで機密に設定することはできません。
  • Imported Batch: オフラインや業務システムから取り込んだバッチ属性(例: ロイヤリティ階層、バッチセグメントの所属)。適切な機密度を必ず設定してください。非機密として指定された場合のみ、ブラウザ向けPersonalization APIのレスポンスに含まれます。

属性の機密度とAPIレスポンス

  • 非機密: ペイロードセクションで参照される属性がすべて非機密であれば、クライアントに返却されます。
  • 機密: ペイロードセクション内に1つでも機密属性が含まれると、そのセクションはクライアントサイド(パブリックトークン)からのリクエストに対して{}としてマスクされます。
  • UIでの制御: 属性の作成/編集フォームでは、機密度の選択が必須です。
  • レビューと監査: UIでは各属性が機密か安全かが表示されます。公開前に属性の一覧を再確認してください。

属性タイプと設計(クライアントサイド)のポイント

Single属性

  • プロパティの最新値のみを保持します(例: last_category_viewed)。
  • PIIの漏えいにつながる恐れがあるSingle属性は避けてください(メール、電話番号、その他の識別子をフロントエンドで見せたくない場合)。
  • 命名のヒント: バッチやサーバーサイド属性と衝突しないよう、明確で重複しない名称を付けます。

List属性

  • セッションや直近の行動に基づくユースケース向けです(例: recent_products_viewed)。
  • 文字列または数値の配列のみを保持します。
  • 価格やURLなどのプロパティを配列として格納でき、リスト全体を保持できますが、集計で主となるフィールドが文字列の場合のみ「フラット化」されます。
  • リスト内の項目が機密データを含む場合は、属性全体を機密に指定する必要があります。
  • 機密集計の数を示すには x/y Sensitive 形式を使用します。たとえば 1/5 Sensitive と設定すると、5つの集計のうち1つが機密であることを意味します。非機密の4つだけがペイロードに含まれるため、レスポンスではその4つの属性のみが返ります。

Counter属性

  • イベント発生数をカウントまたは合計します(例: page_views_last_7_days)。
  • 常に非機密であり、集計行動のみを公開するためリスクが限定的です。
  • スライディングウィンドウ(ローリング)や累積オプションをサポートしており、期間には上限が設定されています。

Imported Batch属性

  • ペアレントセグメントに含めた場合にのみリアルタイムペイロードに追加されます。
  • 取り込み時に明示的に構成し、機密度を設定する必要があります。
  • ブラウザイベントによるリアルタイム更新は行われず、バッチセグメントの再実行時にのみリフレッシュされます。
  • ペアレントセグメントからインポート済みバッチ属性を削除し、RT構成を更新しないままだとエラーになります。必要に応じて属性を再追加し、ペアレントセグメントを再実行するか、ダミーエンティティを作成して解消してください。

属性設計のベストプラクティス(クライアントサイド)

  • まず機密性を優先してください。ブラウザのAPIはエンドユーザーに解析される可能性があることを前提に、PIIや機密ロジックを含む、または推測できる属性を安易に非機密に設定しないでください。
  • 命名規則を徹底し、rtclient といったプレフィックス/サフィックスを付与してクライアントサイド属性を判別しやすくします。
  • 特にリスト属性とカウンター属性では、価値とセキュリティ/コンプライアンスを両立できるウィンドウ期間を選択してください。
  • UIやAPIのプレビュー機能を使い、ブラウザレスポンスに意図した非機密フィールドだけが含まれているかをエンドツーエンドで確認してください。
  • 要件が変わった場合は属性の機密度を更新できますが、変更にはUI/APIでの再設定が必要で、誤設定があるとセクションの一時的なマスクにつながる可能性があります。
  • Audience StudioやAPIペイロードで混乱が起きないよう、クライアントサイド属性とバッチ/サーバーサイド属性を明確に区別してください。

まとめ表: 属性タイプと機密度の扱い

属性タイプ機密度の指定が必要かクライアントサイドでの公開補足
Single必須非機密のみプロファイルごとの最新値
List必須非機密のみ最大100件、60日で期限切れ
Counter常に非機密非機密のみカウント/集計のみ
Imported Batch必須非機密のみ参照のみ。リアルタイムイベントで更新されない

ステップ4: プロファイル統合とIDステッチ(クライアントサイド)

プロファイル統合(IDステッチとも呼ばれます)は、特定の顧客に関係するブラウザ由来のイベントとバッチイベントを1つの統合プロファイルにまとめる機能です。このセクションでは、クライアントサイド統合でのステッチの設定方法を解説します。

クライアントサイドパーソナライゼーションにおけるプロファイル統合とは

クライアントサイドのパーソナライゼーションでは、顧客が複数のデバイスやブラウザからアクセスし、匿名状態と認証済み状態を行き来することがあります。タッチポイントを統合することで、文脈が変わっても関連性の高いリアルタイム体験と正確なオーディエンスセグメンテーションを実現できます。

IDステッチでは、イベントに含まれる識別子(匿名ブラウザID、ファーストパーティクッキー、許可される範囲での非機密な顧客IDなど)を連携させ、閲覧行動、セグメント所属、コンテキスト属性を単一の顧客プロファイルにひも付けます。

クライアントサイドでのIDステッチ設定手順

  1. ブラウザ向けに適切な識別子を選択

    • クライアントサイドで公開しても安全な非機密IDのみを使用します。例:
    • td_client_id(匿名化されたシステム付与ID)
    • ファーストパーティのブラウザまたはセッションクッキー(PIIでない場合)
    • サイト固有の訪問者ID
    • ブラウザイベントやクライアントサイドのステッチキーとして、メールアドレス、ハッシュ化PII、生のユーザー情報を使用しないでください。
  2. リアルタイム構成UIでステッチキーを定義

    • 「ID Stitching Keys」セクションで、ステッチ対象にする非機密のクライアントサイド識別子を追加します。
    • 必要に応じて正規表現を設定し、受信したIDのフィルタリングや形式統一を行えます。
    • 応用: 「workflow only」を設定すると、バッチ/ステージング専用にし、リアルタイムブラウザイベントでは使用しないようにできます。
  3. プライマリキーを設定

    • 利用可能なキーを定義したら、ユニークで永続的、かつ安定した識別子をプライマリキーとして選択します。
    • このキーはすべて(もしくはほぼすべて)のクライアントイベントに含まれ、予期せず変化しない必要があります。
    • 例: td_client_id を全ブラウザセッションで設定していればプライマリキーとして適しています。
    • 統合システムは、最も古いプライマリキーを正規のプロファイルとして割り当て、イベントと属性を統合します。
  4. 構成を保存し、検証

    • ステッチキーとプライマリキーを設定したら、保存してプロファイル統合ワークフローを再起動します。
    • 注意: 有効化後にプライマリキーを変更すると、プロファイルの再処理が必要になり、一時的にセグメンテーションが欠落する場合があります。

クライアントサイドIDステッチにおけるプライバシーとコンプライアンスの注意点

  • クライアントサイドで使用する識別子はすべて非機密である必要があります。ブラウザからメールアドレス、電話番号、住所、直接的/ハッシュ化済みのPIIを送信したりステッチしたりしないでください。
  • GDPRやCPRAなどの法規制、貴社のプライバシーポリシーを確認し、クロスデバイス/ユーザー統合を実施する際には適切な同意管理を徹底してください。
  • 一時的なIDやセッション単位、デバイス単位の識別子をクライアントサイドのフローでは推奨します。

ベストプラクティスと代表的なシナリオ

  • クロスデバイスユーザーに備えましょう。匿名ユーザーが後にログインするケースなど、ブラウザ識別子がプライバシーポリシーに準拠した非機密キーに確実にマッピングされるよう設計してください。
  • ステッチに使用する識別子を監査し、本番稼働前にPIIやPIIに推測され得る情報が含まれていないか再確認してください。
  • ボットトラフィックやテスト、無効なセッションからの識別子を除外するために、正規表現や値の除外設定を活用し、クリーンな統合対象を維持してください。

例:

ユーザーが匿名状態で td_client_id=a123 として閲覧し、後でシステム生成のユーザーIDでログインした場合(イベントではメールを使用しないと仮定)、非機密キーを通じて両方のセッションを結合し、最も古い識別子を持つプロファイルに統合できます。

システム制約

  • ペアレントセグメントあたり最大200個のステッチキーを設定できます。
  • 各プロファイルは、セグメント内で常に単一の非PIIプライマリキーに解決される必要があります。
  • 稼働後にプライマリキーを変更する場合は、プロファイルステッチを再実行して整合性を保たなければなりません。

まとめ表: クライアントサイド統合におけるIDステッチ

ステップクライアントサイドでの指針
許可されるIDタイプ非機密のブラウザID、匿名トークン、非PIIユーザーID
禁止されるIDタイプメール、電話番号、ハッシュ化PII、その他の機密属性
設定UIでの挙動機密性に関する警告を表示。有効化後は編集不可。UIで検証を実施
最大ステッチキー数200
キーの割り当て一意で安定した値を選択し、稼働後の変更は避ける
マージロジック最も古いIDを正規プロファイルとして採用

ステップ5: Audience Studioでのパーソナライゼーション構築と管理(クライアントサイド)

イベントテーブルとリアルタイム属性を設定し、それぞれの機密度を確定したら、Audience Studioでクライアント向けのパーソナライゼーションロジックを設計して公開します。このフェーズでは、ブラウザに安全なリアルタイムAPIレスポンスを通じて各訪問者に適切なオファーやコンテンツを届ける方法を定義します。クライアントサイド製品のワークフローは、プライバシーを最大化し、非機密のペイロードのみを返すこと、さらに公開範囲を監査できるUI表示を提供するよう設計されています。

クライアント向けパーソナライゼーションの作成と管理

  1. ペアレントセグメントにアクセスして新しいパーソナライゼーションを作成

    • Audience Studioで対象のペアレントセグメントを開きます。
    • 「Create」から「Personalization」を選択し、今後の管理に役立つ名前と任意の説明を入力します。
  2. セクションごとの条件とペイロードを定義

    • Personalization Canvasで新しいパーソナライゼーションを開きます。
    • 1つ以上の「セクション」を追加します。各セクションには次の要素があります。
      • 条件: パーソナライゼーションを発火させるルール(例: is_new_visitor = true
      • ペイロード: 条件に一致したときブラウザへ返すデータ/オファー。事前に構成したバッチセグメントとリアルタイム属性から構成します。
  3. 属性の機密度がペイロードの可視性を左右

    • クライアントサイドのエンドポイントでは、非機密属性のみで構成されたセクションだけがブラウザにデータを返します。
    • セクション内にSingle/List/Importedいずれかの機密属性が含まれている場合、APIはそのセクションを{}として返し、完全にマスクします。
    • UIには盾や鍵のアイコンなどの視覚的な合図が表示され、ブラウザ/パブリックトークンでリクエストした際にセクションが空になるかどうかを確認できます。
  4. プライバシーとコンプライアンスのためのUI/ワークフローのヒント

    • セクションビルダーは属性の機密度を自動検査し、リアルタイムで表示を更新します。
    • 返却フィールドにエイリアスを設定したり、オーディエンス/バッチセグメントを追加したりできますが、クライアントに公開したい場合はこれらも非機密として構成する必要があります。
    • レスポンスSLAとフロントエンドの高速性のため、ペイロードサイズは10KB未満、理想的にはセクションごとに20属性未満に抑えてください。
    • バッチセグメント、インポート属性、機密度ラベルを変更した場合は、ペアレントセグメントのワークフローを再実行し、最新の出力がユーザーに配信されるようにします。
  5. マスク(レダクション)ロジックの適用

    • ブラウザからパブリックトークンでパーソナライゼーションを呼び出す場合、機密属性を参照するセクションは必ずマスクされます。残りが非機密であっても例外はありません。
    • 例: 「Recommended Coupon」セクションで機密のインポート属性を参照すると、offers["Recommended Coupon"] はクライアントレスポンスで {} になります。

一貫性、テスト、監査性

  • 公開する想定のオファーが機密フィールドを参照しないよう、露出範囲を意識してパーソナライゼーションロジックを設計します。
  • UIの「Preview」や「Test」機能を使用し、ブラウザでどのセクション/属性が表示されるかを確認してください。
  • フィールド名や用途を文書化し、どのセクションがクライアント公開に適しているかをチーム(エンジニア、プロダクトマネージャーなど)と共有してください。

例: ペイロードのマスク挙動

次の2つのセクションを構成したとします。

  • Welcome Banner

    • ペイロード: { "welcome_message": "Hello, new user!" }
    • すべての属性が非機密
    • クライアントサイドAPIのレスポンスに表示されます。
  • Loyalty Discount

    • ペイロード: { "discount_code": "LOYAL-15", "membership_tier": バッチ属性(機密) }
    • 少なくとも1つの機密属性を含む
    • マスクされ、APIはこのセクションを空オブジェクトとして返します。

まとめ表: パーソナライゼーションセクションの結果

セクション名使用する属性機密属性の有無クライアントAPIの結果
Welcome Bannerwelcome_message(非機密)いいえ{ "welcome_message": ... } を返す
Loyalty Discountdiscount_codemembership_tierはい{}(セクションがマスクされる)

ベストプラクティス

  • 本番公開前にすべてのペイロードセクションを監査してください。
  • マーケティングやコンテンツチームがどのオファーを公開できるか把握できるよう、ドキュメントを更新します。
  • 機密性に関する誤解が生じる可能性がある場合は、セクションに不要な属性を含めないようにしてください。
  • 視覚的なインジケーターやUIの警告を必ず確認し、公開予定であるにもかかわらずロック/マスクされていないかをチェックしてください。

ステップ6: API統合と実装例(クライアントサイド)

このセクションでは、ブラウザのJavaScriptからリアルタイムパーソナライゼーション2.0を統合し、ページ内体験でパーソナライズされたオファーを安全かつ効率的に取得する手順を紹介します。パブリックトークン、CORS対応エンドポイント、リクエスト/レスポンスの設計パターン、そしてサーバーサイド実装とのプライバシー/セキュリティ面の違いに焦点を当てます。

ブラウザからパーソナライゼーションAPIを呼び出す

クライアントサイド統合では、ブラウザのJavaScriptから直接呼び出せる安全なCORS対応エンドポイントを使用します。すべてのリクエストでパブリックRTパーソナライゼーショントークンを使用し、プライベート/サーバーサイド用トークンは絶対に使わないでください。

例: ブラウザからのfetchリクエスト

https://us01.p13n.in.treasuredata.com/public/<YOUR_DB_NAME>/<YOUR_TABLE_NAME>

注意事項:

  • リージョン固有のドメインと /public/ パスをクライアント/ブラウザ呼び出しで使用してください。
  • <YOUR_DB_NAME> はストリーミングイベント用のデータベースです。
  • <YOUR_TABLE_NAME> はリアルタイムイベントのテーブルです。

APIエンドポイントの例

fetch('https://us01.p13n.in.treasuredata.com/public/my_shop_db/event_table', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/vnd.treasuredata.v1+json',
    'WP13n-Token': '12345/3/PUBLIC_TOKEN_ABC',
    'Authorization': 'TD1 <WRITE API KEY>'
  },
  body: JSON.stringify({
    td_client_id: '1986b2a4-3957-4863-be2c-7ef36a14afee',
    td_url: window.location.href,
    td_path: window.location.pathname,
    product_name: 'women’s-tank-top',
    product_category: 'women',
    product_list: ['women’s-running-shoes', 'kids’-hoodie', 'women’s-tank-top'],
    category_list: ['women', 'kids']
    // ... any other non-sensitive fields you’ve configured
    })
  })
  .then(response => response.json())
  .then(data => {
    // Handle personalization offers here, e.g., update UI sections
    console.log('Personalization Offers:', data.offers);
});

例: ブラウザからのfetchリクエスト

fetch('https://us01.p13n.in.treasuredata.com/public/my_shop_db/event_table', {
method: 'POST',
headers: {
  'Content-Type': 'application/vnd.treasuredata.v1+json',
  'WP13n-Token': '12345/3/PUBLIC_TOKEN_ABC',
  'Authorization': 'TD1 <WRITE API KEY>'
  },
body: JSON.stringify({
  td_client_id: '1986b2a4-3957-4863-be2c-7ef36a14afee',
  td_url: window.location.href,
  td_path: window.location.pathname,
  product_name: 'women’s-tank-top',
  product_category: 'women',
  product_list: ['women’s-running-shoes', 'kids’-hoodie', 'women’s-tank-top'],
  category_list: ['women', 'kids']
        // ... any other non-sensitive fields you’ve configured
  })
})
.then(response => response.json())
.then(data => {
  // Handle personalization offers here, e.g., update UI sections
  console.log('Personalization Offers:', data.offers);
});

ベストプラクティス

プライベートRTトークンやTD APIキーをフロントエンド/ブラウザコードに埋め込まないでください。公開用(publishing)のトークンのみを使用します。

CORSとセキュリティ制御

  • CORSヘッダーが返される条件:
    • 有効でアクティブなパブリックトークンを使用している。
    • Originヘッダーが許可されたブラウザオリジンと一致している(TDの設定に基づく)。
  • ブラウザのJavaScriptでプライベートトークンや誤ったエンドポイントを使用すると、CORSヘッダーのない4xxエラーが返され、ブラウザ側ではリクエストが失敗します。
  • トークンが有効でも、ペイロードで「Sensitive」に指定された属性を参照すると、該当セクションは空になります(後述の例を参照)。

APIリクエストとレスポンスの例

例: リクエスト(JSON)

{
  "td_client_id": "42a508e2-d9b1-4baa-9eb2-6c3fb8bd5e16",
  "td_url": "https://treasuredemos.com/retail/shop/women",
  "td_path": "/retail/shop/women",
  "product_name": "women’s-tank-top",
  "product_category": "women",
  "product_list": [
    "women’s-running-shoes",
      "kids’-hoodie",
      "women’s-tank-top"
  ],
  "category_list": [
    "women",
    "kids"
  ]
}

例: 正常なレスポンス(非機密属性のみ)

{
  "offers": {
    "Welcome Banner": {
      "attributes": {
        "welcome_message": "Welcome to our website! Enjoy your shopping!"
      }
    },
    "Silver rewards just for you!": {
      "attributes": {
        "first_name": "John",
        "total_purchase": 28700,
        "items_purchased": [],
        "order_summary": "Here is your order summary!",
        "thank_you_message": "Thank you for shopping with us!",
        "promotions_message": "Enjoy your 15% discount for your next purchase!"
      }
    }
  }
}

機密属性が含まれている場合のレスポンス例

{
  "offers": {
    "Welcome Banner": {
      "attributes": {
        "welcome_message": "Hello, new user!"
      }
    },
    "Loyalty Discount": {} // This section references a sensitive attribute and is redacted
  }
}

補足:

  • すべての属性が非機密で構成されたセクションだけがクライアントに返ります。
  • 厳格なマスク処理により、PIIや保護対象データがブラウザに送られることはありません。
  • UIで機密とマークされた属性が1つでも含まれるセクションは、レスポンスでマスクされます。

クライアント統合とサーバー統合の比較

項目クライアントサイドAPI呼び出しサーバーサイドAPI呼び出し
エンドポイント/public/{db}/{table}/{db}/{table} (/public なし)
トークンタイプパブリックのみ(publishing)プライベートまたはパブリック(構成可能)
追加認証ブラウザでAPIキーを使用サーバーヘッダーでAPIキーを使用
CORS必須。条件不一致の場合はブロック使用/必須ではない
機密属性マスクされ、該当セクションは {}権限があれば常に含まれる
IPホワイトリストパブリック/ブラウザトークンでは不可プライベート/サーバートークンでサポート

トラブルシューティングとベストプラクティス

  • 403/401/またはCORSエラーが発生する場合
    • 該当のパーソナライゼーションサービスに対して有効なパブリックトークンを使用しているか確認してください。
    • Originが許可されており、エンドポイントパスに /public/ が含まれているか確認してください。
  • レスポンスが空/ブランクの場合
    • Audience StudioのUIで属性の機密度を確認してください。非機密属性のみがブラウザに返されます。
  • 将来のSDKサポートについて
    • 公式のTD JS SDKが更新されるまでは、上記のようなネイティブfetch/XHRパターンを使用してください。