# Lookup Catalog

**Lookup Catalog** は、RT 2.0 パーソナライゼーションがリクエストを受け取った瞬間に、商品カタログ・クーポン定義・セールスケジュールなどの外部ビジネスデータを参照できる機能です。ユーザーごとの値を保持するプロファイルアトリビュートとは異なり、Lookup Catalog のデータは `product_id` のような**ユーザー以外のディメンション**をキーとして持ち、RT 2.0 の内部ストレージからリアルタイムに照会されます。

## Lookup Catalog を使用するタイミング

パーソナライゼーションのレスポンスに、商品・SKU・クーポン・その他のユーザー以外のディメンションによって異なるデータを含める必要がある場合に Lookup Catalog を使用します。

- 現在表示中の商品に対する割引率と終了日を含むセールバナーを返す。
- ユーザーがカートに追加した商品に適用できるクーポンを持っている場合のみ、クーポンリマインダーを返す。
- ユーザーが最後に閲覧したアイテムをキーとした商品レコメンドのメタデータを返す。


ユーザーごとのアトリビュート（氏名・ティア・購入履歴など）のみが必要な場合は、代わりに [Real-time Attributes](/ja/products/customer-data-platform/real-time/real-time-attributes-overview) を使用してください。

## Lookup Catalog の仕組み

```mermaid
flowchart TD
    A[("cdp_lookup_catalog\ndatabase")] -->|Treasure Workflow\nscheduled upload| B[("RT 2.0\nInternal Storage")]
    B -->|Queried on each\np13n API call| C[Personalization Response]
    C --> D[Client / SDK]
```

1. データエンジニアが Data Workbench の `cdp_lookup_catalog` データベースにルックアップテーブルを作成・管理し、Treasure Workflow の同期ワークフローを実行して RT 2.0 の内部ストレージにデータをプッシュします。
2. Audience Studio で、ペアレントセグメントに Lookup Catalog Attribute を作成し、カタログテーブルをランタイムルックアップキー（RT アトリビュートの値）に紐付けます。
3. パーソナライゼーションリクエストが届くと、RT 2.0 はランタイムキーの値を使って対応する行を照会し、カラムの値をオファーペイロードの一部として返します。
4. クライアントが返された値をレンダリングします。たとえば TD Web SDK は Liquid が解決した HTML を DOM のゾーンやポップアップに描画します。


## Step 1 — ルックアップカタログデータの準備

データエンジニアは Data Workbench の `cdp_lookup_catalog` データベースにルックアップテーブルを作成・管理します。

### データベースとテーブルの規則

- データベースは通常 `cdp_lookup_catalog` という名前にします。任意の Plazma データベースを使用できますが、この名前が標準的な規則です。
- 主キーは、テーブル内で**最初に現れる `time` 以外のカラム**です。テーブルの先頭カラムが `time` という名前の場合は、2 番目のカラムが主キーとして使用されます。主キーカラムは一意で NULL でない値が必要で、型は `string` でなければなりません。
- その他のカラムには `string`、`number`、`boolean`、または **array** 型（`array<string>`、`array<int>` など）の値を含めることができます。配列のネスト（配列の中に配列がある構造）はサポートされていません。詳細は[制限事項](#%E5%88%B6%E9%99%90%E4%BA%8B%E9%A0%85)を参照してください。
- Lookup Catalog Attribute の設定でカラム名を指定する際は、**Plazma のカラム名**（`queryAs` エイリアスではない）を使用します。
- データはアップロード前に**重複除去・正規化**が必要です。ワークフローは重複除去を行いません。


NULL キー値があるとアップロードが失敗します
主キーのカラムが `NULL` または空の行がある場合、同期ワークフローは 400 エラーで失敗します。アップロード前にすべての行に有効な NULL でないキー値があることを確認してください。

### 例: 商品セールテーブル

`product_id` をキーとする `limited_time_sale` テーブル:

| **product_id**  | **discount_rate**  | **sale_end**  | **banner_html**  |
|  --- | --- | --- | --- |
| `SKU-12345` | `20` | `2026-07-31 23:59` | `<div class='promo'>20% OFF — ends July 31</div>` |
| `SKU-67890` | `15` | `2026-08-15 23:59` | `<div class='promo'>15% OFF — ends August 15</div>` |


保存前に HTML をサニタイズしてください
上記の `banner_html` のようにカラムに生の HTML を保存し、Liquid 経由でクライアントサイドにレンダリングする場合は、取り込み前にその HTML のソースが信頼できるものであり、サニタイズされていることを確認してください。信頼できない、またはユーザー生成の HTML を Lookup Catalog テーブルに保存すると、ブラウザでレンダリングされる際に XSS リスクが生じる可能性があります。

### 例: ユーザー×商品クーポンテーブル

カートレベルのクーポン検索に**複合キー**（`user_id` + `product_id` を結合）を使用する `user_product_coupon` テーブル:

| **user_product_id**  | **has_coupon**  | **coupon_code**  |
|  --- | --- | --- |
| `user_001SKU-12345` | `true` | `SAVE10` |
| `user_001SKU-67890` | `true` | `FLASH15` |


複合キーの順序が重要です
Lookup Catalog Attribute で複数のルックアップキー（たとえば `user_id` + `product_id`）を使用する場合、ランタイムの値は**デリミタなしで**、アトリビュート設定で定義した**キーの順序**で結合されます（例: `user_001` + `SKU-12345` → `user_001SKU-12345`）。テーブルに保存されている複合キーは、この結合結果と完全に一致している必要があります。デリミタを挟むとルックアップが一致しなくなるため、挿入しないでください。

### 配列カラムのサポート

配列型（`array<string>`、`array<bigint>` など）のカラムは完全にサポートされています。1 行にスカラーカラムと配列カラムを混在させることができます。

| **product_id**  | **name**  | **price**  | **tags** (`array<string>`)  |
|  --- | --- | --- | --- |
| `SKU-12345` | `Crew Tee` | `29` | `["sale", "tops", "new-arrival"]` |
| `SKU-67890` | `Wide-leg Pants` | `58` | `["sale", "bottoms"]` |


配列のネストはサポートされていません
多次元配列（配列の中に配列がネストされた構造）はサポートされていません。取り込み前にネスト構造をフラット化してください。

## Step 2 — RT ストレージへのデータアップロード

同期ワークフローは `cdp_lookup_catalog` データベースから読み取り、Bulk Load API を通じて変更されたレコードのみを RT 2.0 の内部ストレージにプッシュします。変更検知にはハッシュベースの手法を使用します。

このワークフローは `cdp_lookup_catalog` 内の対象テーブルをすべて自動検出し、実行ごとに同期します。オプションの `p_table_name` パラメーターを設定すると、実行を単一テーブルに限定できます（テスト用途に便利です）。セットアップ手順・パラメーター一覧・トラブルシューティングについては、[Lookup Catalog Sync Workflow](/ja/products/customer-data-platform/real-time/lookup-catalog-workflow) を参照してください。

データの鮮度
Lookup Catalog データは**バッチ同期**です。ストリーミングではありません。データは最後にワークフローが実行されたときの状態を反映します。カタログデータの変更頻度に合わせて同期スケジュールを設計してください。

## Step 3 — Lookup Catalog Attribute の作成

Audience Studio で、ペアレントセグメントに **Lookup Catalog** アトリビュートを追加します。

1. Audience Studio でペアレントセグメントを開きます。
2. **RT Attributes** の下で **Add Attribute** をクリックし、**Lookup Catalog** を選択します。


![Lookup Catalog タブが選択された Add Attribute ダイアログ。Name、System ID、Description、Lookup catalog table、Lookup columns、Lookup keys の各フィールドが表示されている](/assets/creating-a-lookup-catalog-attribute-2026-07-11.d373a7b776102acdaaa1a17635f338088c381c359ab47aea3e19d8bfb6f054e3.5b2238d2.webp)

1. アトリビュートの各フィールドを設定します:


| **フィールド**  | **説明**  |
|  --- | --- |
| **Name** | アトリビュートの表示名（例: `sale_end_at`）。 |
| **System ID** | Liquid テンプレートや Entry Criteria で使用される内部識別子（例: `sale_end_at`）。**Name** から自動入力されますが変更可能です。 |
| **Description** | 社内ドキュメント用のオプション説明文。 |
| **Lookup catalog table** | ルックアップソースとして使用する `cdp_lookup_catalog` のテーブルを選択します。 |
| **Lookup columns** | レスポンスペイロードに含めるカラムを選択します。**Plazma のカラム名**（`queryAs` エイリアスではない）を使用してください。 |
| **Lookup keys** | RT アトリビュートのタイプ（**Single-Value アトリビュート**、**List Attribute** など）と、行の検索に使用するランタイム値を持つ具体的なアトリビュートを選択します。複合キーには **+ Add Lookup Key** で複数追加できます。**順序が重要** — キーは一覧の順序で結合されて複合ルックアップキーが形成されます。 |


複合キーの順序
複合キーを使用する場合、カタログテーブル内でキーカラムが結合されている順序と同じ順序でルックアップキーを定義してください。順序が一致しないとルックアップが失敗します。

アトリビュート作成後のカラム削除について
Lookup Catalog Attribute を設定した後にカタログテーブルからカラムが削除された場合、アトリビュート設定は自動的には更新されません。次回の同期以降、そのカラムのデータはオファーレスポンスに含まれなくなります。

## Step 4 — エントリー条件の設定（任意）

Lookup Catalog Attribute は Audience Studio の**エントリー条件**で使用でき、パーソナライゼーションのセクションを返すかどうかをサーバーサイドで制御できます。条件が満たされない場合、そのセクションとペイロード全体が API レスポンスから除外されるため、クライアント側に条件分岐ロジックを実装する必要はありません。

### Audience Studio でのエントリー条件設定手順

1. Audience Studio で **Personalization** を開き、対象のセクションに移動します。
2. **Entry Criteria** のキャンバスに、作成した Lookup Catalog Attribute をドラッグ＆ドロップして条件スロットに追加します。
3. 演算子と値を選択します。たとえば、ユーザー×商品の組み合わせでクーポンが存在する場合のみセクションを返すには:
  - アトリビュート: `product_coupon` → カラム: `has_coupon`
  - 演算子: `==`
  - 値: `"true"`


リクエスト時にこの条件が満たされない場合、セクション全体がパーソナライゼーションレスポンスから除外されます。

リクエストに lookup_key は不要
API リクエストに `lookup_key` フィールドを明示的に渡す必要は**ありません**。RT 2.0 が **Lookup keys** で定義された順序でランタイムアトリビュートの値を自動的に結合し、内部でカタログデータを照会します。

### スカラーカラムの演算子

| **演算子**  | **説明**  |
|  --- | --- |
| `==` | 値と等しい |
| `!=` | 値と等しくない |
| `<`, `<=`, `>`, `>=` | 数値またはタイムスタンプの比較 |
| `IS NULL` / `IS NOT NULL` | NULL チェック |
| `AND` | 複数の条件を結合 |


### 配列カラムの演算子

Lookup Catalog のカラムが配列型で、ルックアップキーが **Single-Value アトリビュート**（単一キールックアップ）の場合、以下の演算子が適用されます:

| **演算子**  | **`array_matching`**  | **セマンティクス**  |
|  --- | --- | --- |
| `Contain` | `any` | 配列内のいずれかの要素に指定した部分文字列が含まれているか |
| `In` | `any` | 配列内のいずれかの要素が右辺の値のいずれかと完全に一致するか |
| `In` | `all` | 配列内のすべての要素が右辺の値のいずれかと完全に一致するか |


配列カラムに対して `Contain` または `In` を使用する場合、`array_matching` は必須です。`not: true` フラグを指定するとどちらの演算子も反転します。

OR はサポートされていません
現在のリリースでは、Lookup Catalog Attribute のエントリー条件における `OR` ロジックはサポートされていません。必要な場合は、それぞれ別のエントリー条件を持つ複数のセクションを使用してください。

## Step 4b — パーソナライゼーションペイロードへの追加

Lookup Catalog Attribute の値を API レスポンスに含めるには、Audience Studio の Personalization セクション設定で **Attribute Payload** にアトリビュートを追加します。

1. Audience Studio で **Personalization** のセクション設定を開きます。
2. **Attribute Payload** の下に、返したい Lookup Catalog Attribute のカラムを追加します。
3. 設定を保存します。


M2 では、Lookup Catalog Attribute はファーストクラスアトリビュートとして扱われ、Single・Counter・List アトリビュートと同様に レスポンスの `attributes` サブセクションに含まれます。

### パーソナライゼーション API レスポンス構造

リクエストがエントリー条件を満たした場合、Lookup Catalog Attribute の値は `offers.<section_name>.attributes` の下に返されます:

```json
{
  "offers": {
    "Coupon Reminder": {
      "attributes": {
        "product_coupon - has_coupon": "true",
        "product_coupon - coupon_ids": "CPN008"
      },
      "batch_segments": null,
      "td_app": null
    }
  }
}
```

エントリー条件が満たされない場合（例: そのユーザー×商品の組み合わせでクーポンが存在しない）、セクション全体が除外されます:

```json
{
  "offers": {}
}
```

## ユースケース

### 期間限定セールバナー

特定の商品にセールが設定されている場合のみ、商品詳細ページにインラインのセールバナーを表示します。

1. `product_id` をキーとし、`discount_rate` と `sale_end` カラムを持つ `limited_time_sale` テーブルを作成します。
2. 現在の `product_id` をルックアップキーとして保持する Single-Value RT アトリビュートを使用して、Lookup Catalog Attribute（`sale_info`）を作成します。
3. エントリー条件を設定します: `sale_info.discount_rate IS NOT NULL` — 該当商品のセール行が存在する場合のみセクションが返されます。


### カートクーポンリマインダー

ユーザーがカートに追加した商品に適用できるクーポンを持っている場合、クーポンリマインダーを表示します。

1. 複合キー（`user_id` + `product_id`）と `has_coupon`、`coupon_code` カラムを持つ `user_product_coupon` テーブルを作成します。
2. ルックアップキーを 2 つ指定して Lookup Catalog Attribute（`coupon`）を作成します: まず `user_id`、次に `product_id`（最後に追加した商品を保持する RT アトリビュート）。
3. エントリー条件を設定します: `coupon.has_coupon == "true"`。


### インタレストタグパーソナライゼーション（配列カラム）

配列カラムに保存された商品に関連するキーワードを基に、パーソナライズされたタグを表示します。

1. `product_id` キーと `array<string>` 型の `keywords` カラムを持つ `product_tags` テーブルを作成します。
2. 現在の `product_id` をルックアップキーとして使用する Lookup Catalog Attribute（`interest_tags`）を作成します。
3. 任意でエントリー条件を設定します: `interest_tags.keywords Contain "sale"` （`array_matching: any`）。


## 制限事項

| **制限事項**  | **詳細**  |
|  --- | --- |
| **バッチ同期のみ** | データはリアルタイムに更新されません。ソーステーブルへの変更は、次回の同期ワークフロー実行後に反映されます。 |
| **配列のネストは非対応** | 多次元配列（配列の中にネストされた配列）はサポートされていません。取り込み前にネスト構造をフラット化してください。 |
| **キーカラムの制約** | 主キーはテーブル内で最初に現れる `time` 以外のカラムでなければならず、`NULL` 値を含めてはならず、型は `string` でなければなりません。 |
| **スキーマ変更時にはダイジェストのリセットが必要** | 主キーカラムを変更した場合、次回のワークフロー実行前にダイジェストテーブル（`_wf_{table_name}_digests`）を削除して再作成する必要があります。アップロード済みのデータは自動的には削除されません。 |
| **センシティブなルックアップキー** | Audience Studio でセンシティブとしてマークされたルックアップキーは、クライアントサイドのパーソナライゼーションリクエストでは使用できません。センシティブなアトリビュートをルックアップキーとして使用した場合、クライアントサイドのリクエストではそのセクション全体がレスポンスから削除されます。 |