> ## Documentation Index
> Fetch the complete documentation index at: https://adcp-docs-ja.pier1.co.jp/llms.txt
> Use this file to discover all available pages before exploring further.

# Universal Macros

> AdCP のユニバーサルマクロは、インプレッション時に置き換えられるプラットフォーム非依存のプレースホルダーで、動的なトラッキングデータをクリエイティブに挿入します。

ユニバーサルマクロにより、バイヤーは各パブリッシャーの広告サーバーの実装詳細を知らなくても、動的なトラッキングデータをクリエイティブに含められます。マクロは、インプレッション時に実際の値に置き換えられるプレースホルダーです。

## 概要

AdCP にクリエイティブアセットを提供する際、次の場所にユニバーサルマクロのプレースホルダーを含められます:

* インプレッショントラッキング URL
* クリックトラッキング URL
* VAST トラッキングイベント
* ランディングページ URL

**例**:

```
https://track.brand.com/imp?
  campaign={MEDIA_BUY_ID}&
  creative={CREATIVE_ID}&
  device={DEVICE_ID}&
  cb={CACHEBUSTER}
```

インプレッション時に、これは次のようになります:

```
https://track.brand.com/imp?
  campaign=mb_spring_2025&
  creative=cr_video_30s&
  device=ABC-123-DEF&
  cb=87654321
```

## フォーマット別に利用可能なマクロ

クリエイティブフォーマットによってサポートするマクロが異なります。各フォーマットで利用可能なマクロを確認するには `list_creative_formats` を使います。

### 共通マクロ（すべてのフォーマット）

| マクロ              | 説明                     | 値の例                 |
| ---------------- | ---------------------- | ------------------- |
| `{MEDIA_BUY_ID}` | あなたの AdCP メディアバイ識別子    | `mb_spring_2025`    |
| `{PACKAGE_ID}`   | あなたの AdCP パッケージ識別子     | `pkg_ctv_prime`     |
| `{CREATIVE_ID}`  | あなたの AdCP クリエイティブ識別子   | `cr_video_30s`      |
| `{CACHEBUSTER}`  | キャッシュを防ぐための乱数          | `87654321`          |
| `{TIMESTAMP}`    | ミリ秒単位の Unix タイムスタンプ    | `1704067200000`     |
| `{CLICK_URL}`    | パブリッシャーのクリックトラッキング URL | *（セールスエージェントが自動挿入）* |

### プライバシーとコンプライアンスマクロ

**規制コンプライアンスに不可欠** - クリエイティブのロジックでユーザーのプライバシー選択を尊重するためにこれらを使います。

| マクロ                   | 説明                                  | 値の例                                                   |
| --------------------- | ----------------------------------- | ----------------------------------------------------- |
| `{GDPR}`              | GDPR 適用フラグ                          | `1`（適用）、`0`（非適用）                                      |
| `{GDPR_CONSENT}`      | IAB TCF 2.0 同意文字列                   | `CPc7TgPPc7TgPAGABC...`                               |
| `{US_PRIVACY}`        | US Privacy（CCPA）文字列                 | `1YNN`                                                |
| `{GPP_STRING}`        | Global Privacy Platform 同意文字列       | `DBABMA~CPXxRfAPXxRfAAfKABENB-CgAAAAAAAAAAYgAAAAAAAA` |
| `{GPP_SID}`           | 適用セクションを示す GPP セクション ID             | `7`、`7,8`（US National、US National + California）       |
| `{IP_ADDRESS}`        | ユーザーの IP アドレス（プライバシーのためにしばしばマスクされる） | `203.0.113.42`、`""`（制限時）                              |
| `{LIMIT_AD_TRACKING}` | Limit Ad Tracking が有効               | `1`（制限）、`0`（許可）                                       |

> **プライバシー警告**: `{IP_ADDRESS}` は GDPR や多くのプライバシー規制の下で個人データとみなされます。このマクロは、ユーザーのプライバシー設定、パブリッシャーのポリシー、地域の規制に応じて、空文字列またはマスク/切り詰めされた IP を返すことがあります。可能な限り、代わりに geo マクロ（`{COUNTRY}`、`{REGION}`、`{CITY}`）を使ってください。

**例 - プライバシーに配慮したトラッキング**:

```javascript theme={null}
// In creative logic
if (GDPR == 1 && GDPR_CONSENT == '') {
  // No consent - don't load tracking pixels
} else {
  // Load tracking
}
```

### デバイスと環境マクロ

| マクロ              | 説明                    | 値の例                                      |
| ---------------- | --------------------- | ---------------------------------------- |
| `{DEVICE_TYPE}`  | デバイスカテゴリ              | `mobile`、`tablet`、`desktop`、`ctv`、`dooh` |
| `{OS}`           | オペレーティングシステム          | `iOS`、`Android`、`tvOS`、`Roku`            |
| `{OS_VERSION}`   | OS バージョン              | `17.2`、`14.0`                            |
| `{DEVICE_MAKE}`  | デバイスメーカー              | `Apple`、`Samsung`、`Roku`                 |
| `{DEVICE_MODEL}` | デバイスモデル               | `iPhone15,2`、`Roku Ultra`                |
| `{USER_AGENT}`   | 完全なユーザーエージェント文字列      | `Mozilla/5.0 ...`                        |
| `{APP_BUNDLE}`   | アプリバンドル ID（ドメインまたは数値） | `com.publisher.app`、`123456789`          |
| `{APP_NAME}`     | 人間が読めるアプリ名            | `Publisher News App`                     |

### 地理情報マクロ

| マクロ         | 説明                                                                                           | 値の例                                                     |
| ----------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| `{COUNTRY}` | ISO 3166-1 alpha-2 国コード                                                                      | `US`、`GB`、`CA`、`FR`、`JP`、`AU`                           |
| `{REGION}`  | 州/県/地域コード                                                                                    | `NY`、`CA`（米国の州）、`ON`（カナダ）、`IDF`（フランス）、`NSW`（オーストラリア）    |
| `{CITY}`    | 都市名                                                                                          | `New York`、`London`、`Tokyo`、`Sydney`                    |
| `{ZIP}`     | 郵便番号                                                                                         | `10001`（米国）、`SW1A 1AA`（英国）、`75001`（フランス）、`100-0001`（日本） |
| `{DMA}`     | [Nielsen DMA コード](https://help.thetradedesk.com/s/article/Nielsen-DMA-Regions)（米国の TV マーケット） | `501`（New York）、`803`（Los Angeles）                      |
| `{LAT}`     | 緯度                                                                                           | `40.7128`、`51.5074`、`35.6762`                           |
| `{LONG}`    | 経度                                                                                           | `-74.0060`、`-0.1278`、`139.6503`                         |

### アイデンティティマクロ

| マクロ                | 説明                   | 値の例               |
| ------------------ | -------------------- | ----------------- |
| `{DEVICE_ID}`      | モバイル広告 ID（IDFA/AAID） | `ABC-123-DEF-456` |
| `{DEVICE_ID_TYPE}` | デバイス ID の種類          | `idfa`、`aaid`     |

### Web コンテキストマクロ

Web ベースのインベントリ向け:

| マクロ          | 説明                  | 値の例                     |
| ------------ | ------------------- | ----------------------- |
| `{DOMAIN}`   | 広告が表示されるドメイン        | `nytimes.com`           |
| `{PAGE_URL}` | 完全なページ URL（エンコード済み） | `https%3A%2F%2F...`     |
| `{REFERRER}` | HTTP リファラー URL      | `https://google.com`    |
| `{KEYWORDS}` | ページキーワード（カンマ区切り）    | `business,finance,tech` |

### 掲出面とポジションのマクロ

| マクロ               | 説明                      | 値の例                       |
| ----------------- | ----------------------- | ------------------------- |
| `{PLACEMENT_ID}`  | グローバルプレースメント ID（IAB 標準） | `12345678`                |
| `{FOLD_POSITION}` | フォールドに対する位置（ディスプレイ）     | `above_fold`、`below_fold` |
| `{AD_WIDTH}`      | 広告スロットの幅                | `300`、`728`               |
| `{AD_HEIGHT}`     | 広告スロットの高さ               | `250`、`90`                |

### 動画コンテンツマクロ

コンテンツコンテキストを持つ動画フォーマット向け:

| マクロ                | 説明            | 値の例                          |
| ------------------ | ------------- | ---------------------------- |
| `{VIDEO_ID}`       | コンテンツ動画の識別子   | `vid_12345`                  |
| `{VIDEO_TITLE}`    | コンテンツ動画のタイトル  | `Breaking News Story`        |
| `{VIDEO_DURATION}` | コンテンツの長さ（秒）   | `600`                        |
| `{VIDEO_CATEGORY}` | IAB コンテンツカテゴリ | `IAB1`（Arts & Entertainment） |
| `{CONTENT_GENRE}`  | コンテンツジャンル     | `news`、`sports`、`comedy`     |
| `{CONTENT_RATING}` | コンテンツレーティング   | `G`、`PG`、`TV-14`             |
| `{PLAYER_WIDTH}`   | 動画プレーヤーの幅     | `1920`                       |
| `{PLAYER_HEIGHT}`  | 動画プレーヤーの高さ    | `1080`                       |

### 動画広告ポッドマクロ

コマーシャルブレイク内の動画広告向け:

| マクロ              | 説明           | 値の例           |
| ---------------- | ------------ | ------------- |
| `{POD_POSITION}` | 広告ブレイク内の位置   | `1`、`2`、`3`   |
| `{POD_SIZE}`     | このブレイク内の総広告数 | `3`           |
| `{AD_BREAK_ID}`  | 一意の広告ブレイク識別子 | `break_mid_1` |

**注**: 動画フォーマットは、`[CACHEBUSTING]`、`[TIMESTAMP]`、`[DOMAIN]`、`[IFA]` などのすべての [IAB VAST 4.x マクロ](http://interactiveadvertisingbureau.github.io/vast/vast4macros/vast4-macros-latest.html)もサポートします。これらは VAST XML でネイティブに機能します。

### 音声コンテンツマクロ

コンテンツコンテキストを持つ音声フォーマット向け:

| マクロ                 | 説明                 | 値の例                               |
| ------------------- | ------------------ | --------------------------------- |
| `{STATION_ID}`      | ラジオ局またはポッドキャストの識別子 | `WXYZ-FM`、`pod_12345`             |
| `{COLLECTION_NAME}` | 番組またはコレクション名       | `Morning Drive`、`Tech Talk Daily` |
| `{INSTALLMENT_ID}`  | ポッドキャストエピソードの識別子   | `ep_2025_01_15`                   |
| `{AUDIO_DURATION}`  | コンテンツの長さ（秒）        | `3600`                            |

### インプレッション識別

| マクロ               | 説明                                            | 値の例                                                                                   |
| ----------------- | --------------------------------------------- | ------------------------------------------------------------------------------------- |
| `{IMPRESSION_ID}` | インプレッションごとに上流で発行される一意の識別子（パブリッシャーまたは広告判断レイヤー） | `8c9e2f3a-7b1c-4d5e-9f6a-1a2b3c4d5e6f`（UUID）、`01ARZ3NDEKTSV4RRFFQ69G5FAV`（ULID）、または同等 |

`{IMPRESSION_ID}` マクロは、一つのインプレッション機会に対する一意の識別子を運びます。これは汎用のインプレッションキーです——バイヤー、計測ベンダー、アトリビューションプロバイダー、検証サービスはいずれも、この種の識別子を使ってインプレッションイベントを重複排除し、ベンダー間でピクセルの発火を照合し、インプレッションをクリックに結合し、リトライを検出します。値を発行する上流レイヤー（下記の階層を参照）がそれをクリエイティブのトラッキング URL に代入し、インプレッションを識別する必要のある下流のコンシューマは同じ値を使います。

**一般的なユースケース:**

* **インプレッションごとの重複排除。** 単一のインプレッションはしばしば多くのピクセル（インプレッション、ビューアビリティ、動画四分位、完了、サードパーティ検証）を発火します。それらすべてが一つの `{IMPRESSION_ID}` を共有することで、下流のコンシューマは時間や URL ベースのヒューリスティックなしに「これは同じインプレッションか?」を照合できます。
* **TMP クロスアイデンティティの重複排除。** TMP インプレッションが複数のユーザーアイデンティティに解決される場合、バイヤーのインプレッショントラッカーは各アイデンティティのログに同じ `{IMPRESSION_ID}` を書き込み、別個インプレッションのカウントが正しく重複排除されるようにします。[インプレッショントラッカーの実装](/docs/trusted-match/impression-tracker-implementation)を参照。
* **ベンダー間の照合。** アドサーバー、検証ベンダー、計測ベンダー間で配信を比較する広告主は、クロスウォークを構築するのではなく `{IMPRESSION_ID}` で結合します。
* **ピクセルリトライの重複排除。** 二度発火するピクセル（ネットワークリトライ、ページ更新）は同じ `{IMPRESSION_ID}` を運ぶので、id に対するサーバー側の重複排除パスが過剰カウントなしにリトライを捕捉します。

**含めるべきとき:**

* **すべてのインプレッショントラッキング URL に推奨** — マクロは小さく安価で、上記のユースケースはすべて、それが一貫して存在するときに恩恵を受けます。
* **TMP コンテキストのみのインプレッションには必須** — アイデンティティマッチが適格性を返さなかった（または呼ばれなかった）場合で、ピクセルに `{TMPX}` がないとき、`{IMPRESSION_ID}` はバイヤーのインプレッショントラッカーで利用可能な唯一のクロスアイデンティティ重複排除キーです。

**形式は実装の選択です。** プロトコルは、セラーをまたぐ/時間をまたぐ衝突を避けるのに十分なエントロピーを持つ一意性を要求します。ワイヤー形式は固定しません。UUID（任意のバージョン）、ULID、snowflake スタイルの ID、その他の衝突耐性のある識別子スキームはすべて受け入れられます。バイヤーは、重複排除の目的のために値を不透明な文字列として扱わなければなりません（MUST）——パースなし、形式の仮定なし。

**値の三つの有効なソース、優先順位順:**

1. **パブリッシャー側の発行**（最高優先度）: パブリッシャー自身のファーストパーティコードが、インプレッション機会ごとに新鮮な識別子を発行し——例: 広告リクエストが判断レイヤーに到達する前にサーバー側で——それを前方に渡して、判断レイヤーが `{IMPRESSION_ID}` を介して代入できるようにします。コンテキストのみとアイデンティティを持つインプレッションの両方で機能します。
2. **判断レイヤーの発行**（パブリッシャーが発行しなかった場合に使用）: 広告判断レイヤー（Prebid TMP モジュール、アドサーバー、SSP、または同等のクライアント）が、コンテキスト↔アイデンティティの結合点で識別子を発行し、`{IMPRESSION_ID}` を介して代入します。これもコンテキストのみとアイデンティティを持つインプレッションの両方で機能します。
3. **TMPX デコード時のバイヤー側の発行**（フォールバック、アイデンティティを持つもののみ）: 上記のどちらのレイヤーも発行しなかった場合、バイヤーのインプレッショントラッカーが [`インプレッショントラッカーの実装`](/docs/trusted-match/impression-tracker-implementation) に従って TMPX デコード時にローカルで id を発行します。これは `{TMPX}` が存在するときにのみ機能します——コンテキストのみのインプレッションはカバーできません。

各レイヤーは、上流のレイヤーがすでに生成した値に従わなければなりません（MUST）——上位のレイヤーがすでに供給しているのに下位のレイヤーで新鮮な id を発行すると、同じインプレッションのログが二つの id にまたがって分割されてしまいます。実際には、これは次を意味します: パブリッシャーが発行した場合、判断レイヤーはそれをそのまま通し、どちらかが発行した場合、バイヤーはデコード時に発行するのではなくピクセルの値を使います。

**`{CACHEBUSTER}` との関係。** 両者は互換ではありません。`{CACHEBUSTER}` は HTTP の中間者を打ち破るのに十分な低エントロピーのアンチキャッシュ値です。グローバルに一意なインプレッションキーではありません。両方が異なる目的で同じトラッキング URL に現れることがあります。

### TMP 露出トラッキング

| マクロ      | 説明                   | 値の例                      |
| -------- | -------------------- | ------------------------ |
| `{TMPX}` | TMP 露出トークン（HPKE 暗号化） | `k1.dG1weC1leGFtcGxl...` |

`{TMPX}` マクロは、[アイデンティティマッチ](/docs/trusted-match/specification)のレスポンスから暗号化された露出トークンを運びます。これは HPKE を介して暗号化されたユーザーの解決済みアイデンティティトークンを含み、バイヤーのインプレッションピクセルがリアルタイムのフリークエンシーキャップのためにユーザーごとの露出をログできるようにします。パブリッシャーは他のマクロとまったく同じように `{TMPX}` をトラッキング URL に代入します。トークンは不透明です——パブリッシャーはその値をパース、ログ、またはそれに基づいて判断してはなりません（MUST NOT）。

暗号化形式と鍵管理については [TMPX 露出トークン](/docs/trusted-match/specification#tmpx-exposure-tokens)を参照してください。

### AXE 連携（レガシー）

| マクロ      | 説明                           | 値の例                        |
| -------- | ---------------------------- | -------------------------- |
| `{AXEM}` | AXE コンテキストメタデータ（エンコードされたブロブ） | `eyJjb250ZXh0IjoiLi4uIn0=` |

`{AXEM}` マクロはレガシーの AXE 連携に由来します。[TMP](/docs/trusted-match) では、これは次で置き換えられます:

* **構造化されたクリエイティブアセット**は、[オファー](/docs/trusted-match/specification#offer)の `creative_manifest` フィールドに移ります。
* **ユーザーごとの露出トラッキング**は、アイデンティティマッチの [`{TMPX}`](#tmp-露出トラッキング) マクロを使います。

### カタログアイテムマクロ

カタログ駆動のクリエイティブ（カルーセル、ダイナミックプロダクト広告、求人ボード、店舗ロケーター）向け。これらのマクロは、配信時にレンダリングされる特定のカタログアイテムの識別子に解決されます——[`content_id_type`](/docs/creative/catalogs#conversion-events) フィールドを介してコンバージョンイベントの `content_ids` で使われるのと同じ識別子です。

| マクロ                | 説明                       | 値の例                         |
| ------------------ | ------------------------ | --------------------------- |
| `{CATALOG_ID}`     | バイヤー定義のカタログ識別子           | `gmc-primary`、`job-feed`    |
| `{SKU}`            | プロダクト SKU 識別子            | `SKU-12345`                 |
| `{GTIN}`           | Global Trade Item Number | `00013000006040`            |
| `{OFFERING_ID}`    | AdCP オファリング識別子           | `summer-sale`               |
| `{JOB_ID}`         | 求人掲載の識別子                 | `vacancy-amsterdam-chef-42` |
| `{HOTEL_ID}`       | ホテル物件の識別子                | `grand-amsterdam`           |
| `{FLIGHT_ID}`      | フライトルートの識別子              | `AMS-BCN-2025-06`           |
| `{VEHICLE_ID}`     | 車両リスティングの識別子             | `VIN-1234`                  |
| `{LISTING_ID}`     | 不動産リスティングの識別子            | `prop-amsterdam-01`         |
| `{STORE_ID}`       | 店舗ロケーションの識別子             | `amsterdam-flagship`        |
| `{PROGRAM_ID}`     | 教育プログラムの識別子              | `mba-2025`                  |
| `{DESTINATION_ID}` | 旅行目的地の識別子                | `barcelona`                 |

カタログの `content_id_type` に一致するマクロを使います。例えば、`content_id_type: "gtin"` のプロダクトカタログはトラッカー URL で `{GTIN}` を使い、求人カタログは `{JOB_ID}` を使います。

#### カタログコンテンツマクロ

上記のマクロはカタログアイテムの**識別子**に解決されます。カタログ**コンテンツ**マクロは、カタログ駆動のクリエイティブテンプレート（`sponsored_placement` / DPA——Meta DPA、Snap Collection、TikTok Shopping）向けに、カタログアイテムのスカラー**フィールド値**に解決されます。それらは上記の ID マクロの「値を代入する」アナログです: 同じシングルブレースのファミリ、下記の同じ代入安全性のルール、ただトークンが多いだけです。

| マクロ                     | 説明             | `catalog_field`  | 値の例                               |
| ----------------------- | -------------- | ---------------- | --------------------------------- |
| `{ITEM_NAME}`           | アイテム名/タイトル     | `name`           | `Summer Sale`                     |
| `{ITEM_DESCRIPTION}`    | アイテムの説明        | `description`    | `Up to 50% off summer collection` |
| `{ITEM_TAGLINE}`        | プロモーションのタグライン  | `tagline`        | `Start measuring today`           |
| `{ITEM_PRICE}`          | 価格の金額          | `price.amount`   | `29.99`                           |
| `{ITEM_PRICE_CURRENCY}` | ISO 4217 通貨コード | `price.currency` | `USD`                             |

各トークンは、[`field_bindings`](/docs/creative/catalogs#field-bindings) が使う既存の `catalog_field` ドット記法の語彙を介して、文書化されたカタログアイテムのフィールドに 1:1 でマップされます——コンテンツマクロは並行するフィールド語彙を導入し**ません**。五つのトークンは意図的に小さくバーティカル横断的です。バーティカル固有の深いフィールド（例: `star_rating`、`salary.min`）はユニバーサルコンテンツマクロではなく `field_bindings` のスカラーが提供します。URL 値と画像値のフィールド（例: `landing_url`、画像プール）は `field_bindings` を介して `url`/アセットスロットにバインドされ、コンテンツマクロでは**ありません**——URL 全体を `href` 全体として代入すると、下記の `encodeURIComponent` 相当のパーセントエンコーディング契約も壊してしまいます。

**シングルブレース `{MACRO}` のみ。** `{{ダブルブレース}}` は AdCP のコンテンツマクロ構文では**なく**、使ってはなりません（MUST NOT）。ダブルブレースは、セールスエージェントが中和/パーセントエンコードしなければならない下流のアドサーバーマクロ構文（`%%...%%`、`${...}`、`[...]`、`{{...}}`）の一つとして予約されています（下記のネスト展開ルールを参照）。それを AdCP のコンテンツマクロに採用すると、その保証を緩め、`{{...}}` をネイティブに解釈する下流のアドサーバーと衝突します。

どのカタログアイテムがレンダリングされるかは、[`sponsored_placement`](/docs/creative/canonical-formats) フォーマットの `fanout_mode` 列挙（`single_item` / `per_item` / `multi_item_in_creative`）を介して**セラーが宣言**します——バイヤー側の選択フィールドはありません。ML 最適化された DPA サーフェス（Meta Advantage+、TikTok Shopping）では、プラットフォームがバイヤーの作成したオーバーレイテキストをしばしば上書きするため、コンテンツマクロはセラーが尊重してもよい（MAY）バイヤー宣言の**ヒント**であって、保証された代入ではありません。

#### 代入安全性（カタログアイテムマクロ）

カタログアイテムマクロは、値が**バイヤー制御のデータ**（カタログフィード）に由来し、インプレッション時に**パブリッシャー制御のコンテキスト**（インプレッショントラッカー URL、クリックトラッカー URL、VAST トラッキングイベント URL、そしてランディング/クリックスルー URL——上記の [URL 代入対象](#概要)の完全な集合）へ展開される、唯一のマクロクラスです。そのフローは攻撃に隣接しています: `&`、`#`、`?`、CR/LF、はぐれた URL フラグメント、または Unicode の bidi オーバーライドを含むカタログ値は、生で代入されると URL コンテキストから抜け出し、CRLF を介して Host ヘッダーを注入し、または監査ログのレンダリングを偽装する可能性があります。

以下のルールは、上記のすべてのカタログアイテムマクロに適用されます——ID マクロ（`{CATALOG_ID}`、`{SKU}`、`{GTIN}`、`{OFFERING_ID}`、`{JOB_ID}`、`{HOTEL_ID}`、`{FLIGHT_ID}`、`{VEHICLE_ID}`、`{LISTING_ID}`、`{STORE_ID}`、`{PROGRAM_ID}`、`{DESTINATION_ID}`）とコンテンツマクロ（`{ITEM_NAME}`、`{ITEM_DESCRIPTION}`、`{ITEM_TAGLINE}`、`{ITEM_PRICE}`、`{ITEM_PRICE_CURRENCY}`）の両方:

* **エンコード前に Unicode NFC に正規化する。** パーセントエンコーディングの前に、すでに Unicode 正規化形式 C（NFC）でないカタログアイテムの値は、Unicode Standard Annex #15 に従って NFC に正規化しなければなりません（MUST）。セラーとバイヤーは `sync_catalogs` の取り込み時に任意の正規化形式でカタログ値を送ってもよい（MAY）（カタログは供給されたまま保存されます）。NFC への正規化は、カタログ取り込みの要件ではなく、パーセントエンコーディングの直前の代入パイプラインのステップです。このステップがないと、下記の unreserved ホワイトリストのルールを両方とも満たす二つの実装が、同じ視覚的な文字列に対して異なるバイトを生成します——`café`（NFC: U+00E9）と `café`（NFD: U+0065 + 結合 U+0301）はそれぞれ `caf%C3%A9` と `e%CC%81` にエンコードされます。NFC はウェブプラットフォームの慣例（WHATWG URL、HTML5 DOM、W3C Character Model）に一致します。NFKC / NFKD は受け入れ可能な代替では**ありません**——その互換性フォールディングは、全角/半角のバリアントや、日本語/韓国語のリテーラーカタログに正当に現れる視覚的に区別される他のグリフを黙って変異させます。
* **RFC 3986 の `unreserved` 集合にないすべてのオクテットをパーセントエンコードする。** セールスエージェントは、NFC 正規化されたカタログアイテムの値を、URL コンテキスト（クエリ文字列、パスセグメント、またはフラグメント）に代入する前に、RFC 3986 の `unreserved` 文字（`ALPHA / DIGIT / "-" / "." / "_" / "~"`）のみがエスケープされずに残るようにパーセントエンコードしなければなりません（MUST）。非 ASCII オクテットは、RFC 3986 §2.5 に従って UTF-8 エンコード後にパーセントエンコードしなければなりません（MUST）。これは `encodeURIComponent` 相当の契約です: 予約文字（`: / ? # [ ] @ ! $ & ' ( ) * + , ; =`）は期待どおりにエスケープされますが、CR（`%0D`）、LF（`%0A`）、スペース（`%20`）、C0/C1 制御文字、Unicode の bidi オーバーライドもエスケープされます——より広い列挙が、予約文字のみのルールでは開いたままになる CRLF 注入と bidi 偽装のベクターを閉じます。エンコーディングは代入時にちょうど一度適用されます。URL を逐語的に発火する下流の VAST プレーヤーとアドサーバーは期待される契約です——それらは発火前に再デコードせず、してはなりません（MUST NOT）。
* **ネストしたマクロ展開は禁止。** それ自体が AdCP の `{MACRO_NAME}` 構文に一致するテキストを含むカタログアイテムの値は、再展開してはなりません（MUST NOT）。セールスエージェントは AdCP のマクロ代入を一度のパスで行います: ソースのプレースホルダーがリテラル値に置き換えられ、それらのリテラル値は再スキャンされません。`vacancy-{DEVICE_ID}-42` という `{JOB_ID}` の値は、放出された URL では二巡目の展開ではなく、リテラル文字列 `vacancy-%7BDEVICE_ID%7D-42`（ブレースのパーセントエンコード後）を生成します。このルールは AdCP の `{...}` 構文のみを拘束します。下流のアドサーバーマクロ構文（`%%...%%`、`${...}`、`[...]`、`{{...}}`）を含むカタログアイテムの値は、それらを解釈するアドサーバーを対象とするときに中和するのは引き続きセールスエージェントの責任です——上記のルールに従うパーセントエンコーディングは、`%`、`$`、`[`、`]`、`{` がすべて `unreserved` 集合の外に着地するため、通常は十分です。
* **スコープは URL コンテキストのみ。** これらのルールは、カタログアイテムマクロが URL コンテキストに代入されるときに適用されます。カタログアイテムマクロが HTML 属性コンテキスト（例: サーバー側でレンダリングされるバナーテンプレートの `href` または `data-*` 属性）に代入されるとき、この節に従うパーセントエンコーディングはそれ自体では属性コンテキストの抜け出しを防ぎません。レンダラーは追加で HTML 属性エスケープを適用しなければなりません（MUST）——値は URL パーサーと HTML 属性パーサーの両方を生き延びなければならないため、二つのエンコーディングは代替ではなく積層されます。AdCP の規範的な契約は URL コンテキストのケースに限定されます。パブリッシャー側の HTML 属性の扱いはこの仕様のスコープ外です。

非カタログマクロ（`{MEDIA_BUY_ID}`、`{PACKAGE_ID}`、`{CREATIVE_ID}`、`{GEO}`、`{COUNTRY}`、`{DEVICE_TYPE}` など）は、バイヤー供給のフィードデータではなく、パブリッシャーまたはアドサーバーが仲介する状態から埋められます。それらのエンコーディング契約は、慣例によってパーセントエンコードするアドサーバー統合（OpenRTB、VAST）が管理します。このクラスの一部のマクロは攻撃者が偽装可能な入力に由来します（`{USER_AGENT}`、`{REFERRER}`、`{PAGE_URL}`、`{DOMAIN}`、`{APP_BUNDLE}` はリクエストヘッダーやページメタデータに由来）。OpenRTB / アドサーバーのエンコーディング慣例が今日の制御です。この仕様の規範的な MUST は、意図的にバイヤー制御のカタログアイテムクラスにスコープします——ユニバーサルな正規化ルールよりも狭く、検証可能な契約です。

**適合性フィクスチャ。** エンコーディングの動作を固定する参照テストベクター——予約文字の抜け出し、ネスト展開のリテラル保持、CRLF 注入、非 ASCII——は [`static/compliance/source/test-vectors/catalog-macro-substitution.json`](https://github.com/adcontextprotocol/adcp/blob/main/static/compliance/source/test-vectors/catalog-macro-substitution.json) でバージョン管理されています。セールスエージェントは、出荷前に自身の代入コードをこれらのベクターに対して検証すべきです（SHOULD）。

### クリエイティブバリアントマクロ

| マクロ                     | 説明                        | 値の例                     |
| ----------------------- | ------------------------- | ----------------------- |
| `{CREATIVE_VARIANT_ID}` | セラーが割り当てたクリエイティブバリアントの識別子 | `variant_a`、`v2_mobile` |

> **注**: パブリッシャー固有のカスタムマクロは、個々のクリエイティブフォーマット仕様で `extra supported macros` として定義される場合があります。

## 使用例

### トラッキング付き動画クリエイティブ

```json theme={null}
{
  "creative_id": "cr_video_30s",
  "format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "video_30s_vast"
  },
  "assets": {
    "vast_xml": {
      "asset_type": "vast",
      "delivery_type": "inline",
      "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<VAST version=\"4.2\">\n  <Ad>\n    <InLine>\n      <Impression><![CDATA[https://track.brand.com/imp?buy={MEDIA_BUY_ID}&pkg={PACKAGE_ID}&cre={CREATIVE_ID}&device={DEVICE_ID}&domain={DOMAIN}&cb=[CACHEBUSTING]]]></Impression>\n      <Creatives>\n        <Creative>\n          <Linear>\n            <Duration>00:00:30</Duration>\n            <TrackingEvents>\n              <Tracking event=\"firstQuartile\"><![CDATA[https://track.brand.com/q1?buy={MEDIA_BUY_ID}&cb=[CACHEBUSTING]]]></Tracking>\n              <Tracking event=\"complete\"><![CDATA[https://track.brand.com/complete?buy={MEDIA_BUY_ID}&cb=[CACHEBUSTING]]]></Tracking>\n            </TrackingEvents>\n            <VideoClicks>\n              <ClickThrough><![CDATA[https://brand.com/spring?campaign={MEDIA_BUY_ID}]]></ClickThrough>\n            </VideoClicks>\n            <MediaFiles>\n              <MediaFile delivery=\"progressive\" type=\"video/mp4\" width=\"1920\" height=\"1080\">\n                <![CDATA[https://cdn.brand.com/videos/spring_30s.mp4]]>\n              </MediaFile>\n            </MediaFiles>\n          </Linear>\n        </Creative>\n      </Creatives>\n    </InLine>\n  </Ad>\n</VAST>",
      "vast_version": "4.2"
    }
  }
}
```

**主なポイント**:

* AdCP マクロ（`{MEDIA_BUY_ID}`）を VAST マクロ（`[CACHEBUSTING]`）と混在させる
* AdCP マクロは `{CURLY_BRACES}` を使う
* VAST マクロは `[SQUARE_BRACKETS]` を使う
* 両者はシームレスに併用できる

### トラッキング付きディスプレイクリエイティブ

```json theme={null}
{
  "creative_id": "cr_banner_300x250",
  "format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "display_banner_300x250"
  },
  "assets": {
    "banner_image": {
      "url": "https://cdn.brand.com/banners/spring_300x250.jpg",
      "width": 300,
      "height": 250
    },
    "impression_pixel": {
      "url": "https://track.brand.com/imp?buy={MEDIA_BUY_ID}&pkg={PACKAGE_ID}&cre={CREATIVE_ID}&device={DEVICE_ID}&domain={DOMAIN}&cb={CACHEBUSTER}"
    },
    "landing_url": {
      "url": "https://brand.com/spring?campaign={MEDIA_BUY_ID}"
    }
  }
}
```

### トラッキング付き音声クリエイティブ

```json theme={null}
{
  "creative_id": "cr_audio_30s",
  "format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "audio_streaming_30s"
  },
  "assets": {
    "audio_file": {
      "url": "https://cdn.brand.com/audio/spring_30s.mp3",
      "duration_ms": 30000
    },
    "impression_tracker": {
      "url": "https://track.brand.com/imp?buy={MEDIA_BUY_ID}&pkg={PACKAGE_ID}&station={STATION_ID}&show={COLLECTION_NAME}&cb={CACHEBUSTER}"
    }
  }
}
```

### アイテムトラッキング付きカタログ駆動クリエイティブ

```json theme={null}
{
  "creative_id": "cr_product_carousel",
  "format_id": {
    "agent_url": "https://creative.retailer.com/adcp",
    "id": "product_carousel"
  },
  "catalogs": [{
    "catalog_id": "gmc-primary",
    "type": "product",
    "content_id_type": "gtin",
    "tags": ["summer"]
  }],
  "assets": {
    "impression_pixel": {
      "url": "https://track.brand.com/imp?buy={MEDIA_BUY_ID}&catalog={CATALOG_ID}&item={GTIN}&cb={CACHEBUSTER}",
      "url_type": "tracker_pixel"
    },
    "click_tracker": {
      "url": "https://track.brand.com/click?buy={MEDIA_BUY_ID}&catalog={CATALOG_ID}&item={GTIN}",
      "url_type": "tracker_pixel"
    }
  }
}
```

**主なポイント**: `{GTIN}` は配信時に特定のプロダクトの GTIN に解決されます。5 つのプロダクトを表示するカルーセルでは、各プロダクトのインプレッション/クリックがそのプロダクトの識別子とともに発火します——アイテムごとのアトリビューションを可能にします。

## インベントリタイプ別のマクロ利用可否

すべてのマクロがすべてのインベントリタイプで利用できるわけではありません。どのマクロがサポートされるかはフォーマット仕様を確認してください。

**重要**: 以下の列は、異なる環境（アプリ vs Web）で実行できるフォーマットタイプ（ディスプレイ、動画など）を表します。例えば:

* モバイルアプリのディスプレイ広告には `DEVICE_ID` があります（✅\*）が、Web のディスプレイ広告にはありません
* ✅\* の表記は「アプリ内コンテキストでのみ利用可能」を意味します
* フォーマットタイプ + インベントリ環境が実際のマクロ利用可否を決定します

| マクロカテゴリ               | Display | Video | Audio | Native | CTV/OTT | DOOH | Mobile App | Mobile Web | Desktop Web |
| --------------------- | ------- | ----- | ----- | ------ | ------- | ---- | ---------- | ---------- | ----------- |
| **Common**            | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{MEDIA_BUY_ID}`      | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{PACKAGE_ID}`        | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{CREATIVE_ID}`       | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{CACHEBUSTER}`       | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{TIMESTAMP}`         | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| **Privacy**           |         |       |       |        |         |      |            |            |             |
| `{GDPR}`              | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{GDPR_CONSENT}`      | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{US_PRIVACY}`        | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{GPP_STRING}`        | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{GPP_SID}`           | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{IP_ADDRESS}`        | ✅‡      | ✅‡    | ✅‡    | ✅‡     | ✅‡      | ❌    | ✅‡         | ✅‡         | ✅‡          |
| `{LIMIT_AD_TRACKING}` | ✅\*     | ✅\*   | ✅\*   | ✅\*    | ✅       | ❌    | ✅          | ❌          | ❌           |
| **Identity**          |         |       |       |        |         |      |            |            |             |
| `{DEVICE_ID}`         | ✅\*     | ✅\*   | ✅\*   | ✅\*    | ✅       | ❌    | ✅          | ❌          | ❌           |
| `{DEVICE_ID_TYPE}`    | ✅\*     | ✅\*   | ✅\*   | ✅\*    | ✅       | ❌    | ✅          | ❌          | ❌           |
| **Geographic**        |         |       |       |        |         |      |            |            |             |
| `{COUNTRY}`           | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{REGION}`            | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{CITY}`              | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{ZIP}`               | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{DMA}`               | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{LAT}/{LONG}`        | ✅†      | ❌     | ❌     | ✅†     | ❌       | ✅    | ✅†         | ❌          | ❌           |
| **Device**            |         |       |       |        |         |      |            |            |             |
| `{DEVICE_TYPE}`       | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{OS}`                | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{OS_VERSION}`        | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{APP_BUNDLE}`        | ✅\*     | ✅\*   | ✅\*   | ✅\*    | ✅       | ❌    | ✅          | ❌          | ❌           |
| `{USER_AGENT}`        | ✅       | ✅     | ✅     | ✅      | ✅       | ❌    | ❌          | ✅          | ✅           |
| **Web Context**       |         |       |       |        |         |      |            |            |             |
| `{DOMAIN}`            | ✅       | ✅     | ✅     | ✅      | ❌       | ❌    | ❌          | ✅          | ✅           |
| `{PAGE_URL}`          | ✅       | ✅     | ✅     | ✅      | ❌       | ❌    | ❌          | ✅          | ✅           |
| `{REFERRER}`          | ✅       | ✅     | ✅     | ✅      | ❌       | ❌    | ❌          | ✅          | ✅           |
| `{KEYWORDS}`          | ✅       | ✅     | ✅     | ✅      | ❌       | ❌    | ❌          | ✅          | ✅           |
| **Placement**         |         |       |       |        |         |      |            |            |             |
| `{PLACEMENT_ID}`      | ✅       | ✅     | ✅     | ✅      | ✅       | ✅    | ✅          | ✅          | ✅           |
| `{FOLD_POSITION}`     | ✅       | ❌     | ❌     | ✅      | ❌       | ❌    | ✅          | ✅          | ✅           |
| **Video Content**     |         |       |       |        |         |      |            |            |             |
| `{VIDEO_ID}`          | ❌       | ✅     | ❌     | ❌      | ✅       | ❌    | ❌          | ❌          | ❌           |
| `{VIDEO_CATEGORY}`    | ❌       | ✅     | ❌     | ❌      | ✅       | ❌    | ❌          | ❌          | ❌           |
| `{CONTENT_GENRE}`     | ❌       | ✅     | ✅     | ❌      | ✅       | ❌    | ❌          | ❌          | ❌           |
| **Video Ad Pods**     |         |       |       |        |         |      |            |            |             |
| `{POD_POSITION}`      | ❌       | ✅     | ❌     | ❌      | ✅       | ❌    | ❌          | ❌          | ❌           |
| `{POD_SIZE}`          | ❌       | ✅     | ❌     | ❌      | ✅       | ❌    | ❌          | ❌          | ❌           |
| `{AD_BREAK_ID}`       | ❌       | ✅     | ❌     | ❌      | ✅       | ❌    | ❌          | ❌          | ❌           |
| **Audio Content**     |         |       |       |        |         |      |            |            |             |
| `{STATION_ID}`        | ❌       | ❌     | ✅     | ❌      | ❌       | ❌    | ❌          | ❌          | ❌           |
| `{COLLECTION_NAME}`   | ❌       | ❌     | ✅     | ❌      | ❌       | ❌    | ❌          | ❌          | ❌           |
| **TMP Exposure**      |         |       |       |        |         |      |            |            |             |
| `{TMPX}`              | ✅       | ✅     | ✅     | ✅      | ✅       | ✅§   | ✅          | ✅          | ✅           |

**凡例**:

* ✅ = 利用可能
* ❌ = 利用不可
* ✅\* = アプリ内のみ（モバイル Web は不可）
* ✅† = 位置情報の許可が付与されている場合
* ✅‡ = プライバシー規制のためしばしば制限される（空またはマスクされた値を返す場合がある）
* ✅§ = DOOH はピクセル URL ではなく再生ログベースのレポートを使う

**重要な注意**:

* プライバシーマクロ（`{LIMIT_AD_TRACKING}`、`{DEVICE_ID}`）は、ユーザーのプライバシー設定に基づいて空の値を返す場合があります
* 地理情報マクロの精度はパブリッシャーのデータ能力によって異なります
* `{PLACEMENT_ID}` は IAB Global Placement ID 標準を指します

## マクロの仕組み

### 1. 発見

`list_creative_formats` を照会して、各フォーマットがどのマクロをサポートするかを確認します:

```json theme={null}
{
  "format_id": {
    "agent_url": "https://creative.adcontextprotocol.org",
    "id": "video_30s_vast"
  },
  "type": "video",
  "supported_macros": [
    {
      "macro": "{MEDIA_BUY_ID}",
      "category": "identity",
      "description": "AdCP media buy identifier",
      "required": false,
      "privacy_sensitive": false,
      "example_value": "mb_spring_2025"
    },
    {
      "macro": "{DEVICE_ID}",
      "category": "identity",
      "description": "Mobile advertising ID (IDFA/AAID)",
      "required": false,
      "privacy_sensitive": true,
      "example_value": "ABC-123-DEF-456"
    },
    {
      "macro": "{GDPR}",
      "category": "privacy",
      "description": "GDPR applicability flag",
      "required": true,
      "privacy_sensitive": false,
      "example_value": "1"
    }
  ],
  "vast_macros_supported": true
}
```

### 2. クリエイティブにマクロを含める

`{MACRO_NAME}` 構文を使って、トラッキング URL にマクロのプレースホルダーを追加します:

```
https://track.brand.com/imp?campaign={MEDIA_BUY_ID}&device={DEVICE_ID}
```

### 3. セールスエージェントの処理

`create_media_buy` を介してメディアバイを作成すると、セールスエージェントは:

1. **AdCP ID マクロをあなたの実際の ID に置き換える**:
   * `{MEDIA_BUY_ID}` → `mb_spring_2025`
   * `{PACKAGE_ID}` → `pkg_ctv_prime`
   * `{CREATIVE_ID}` → `cr_video_30s`

2. **プラットフォームマクロをそのアドサーバーの構文に変換する**:
   * `{CACHEBUSTER}` → `%%CACHEBUSTER%%`（GAM）または `{{timestamp}}`（Kevel）
   * `{DEVICE_ID}` → `%%ADVERTISING_IDENTIFIER_PLAIN%%`（GAM）
   * `{DOMAIN}` → `%%SITE%%`（GAM）

3. **クリック可能な要素にクリックトラッカーを自動的に挿入する**

4. **VAST マクロは変更しないまま残す**（動画フォーマット向け）

#### SDK による変換の実装

セールスエージェントは書き換えを手作業で組む必要はありません。`@adcp/sdk` パッケージは、マクロごとのマッピングをトラッキング URL のクエリパラメータの値に適用する `translateUniversalMacros` ヘルパーを提供します。各マクロは、**ネイティブ**のアドサーバートークン（生のまま残され、インプレッション時にアドサーバーが埋める）または、エージェントがすでに知っている具体的な**値**（今代入され、RFC 3986 に従ってパーセントエンコードされる）のいずれかにマップされます:

```typescript theme={null}
import { translateUniversalMacros } from '@adcp/sdk';

const mapping = {
  // AdCP identifiers the agent knows at media-buy creation → concrete values
  '{MEDIA_BUY_ID}': { value: 'mb_spring_2025' },
  '{PACKAGE_ID}': { value: 'pkg_ctv_prime' },
  // Runtime macros → the ad server's native syntax (Google Ad Manager shown)
  '{CACHEBUSTER}': { native: '%%CACHEBUSTER%%' },
  '{DEVICE_ID}': { native: '%%ADVERTISING_IDENTIFIER_PLAIN%%' },
};

const { url, dropped_params, unmapped_macros, dropped_consent_macros, suspect_native_values } =
  translateUniversalMacros(
    'https://track.brand.com/imp?buy={MEDIA_BUY_ID}&pkg={PACKAGE_ID}&cb={CACHEBUSTER}&device={DEVICE_ID}',
    mapping,
  );

// url:
//   https://track.brand.com/imp?buy=mb_spring_2025&pkg=pkg_ctv_prime&cb=%%CACHEBUSTER%%&device=%%ADVERTISING_IDENTIFIER_PLAIN%%
// dropped_params: []           (every macro was mapped)
// unmapped_macros: []
// dropped_consent_macros: []   (no consent macro was dropped)
// suspect_native_values: []    (no value entry looks like a native token)
```

動作:

* **`native` エントリは逐語的に挿入されます** — `%%CACHEBUSTER%%` はパーセントエンコードされないため、アドサーバーは依然としてそれを認識します。
* **`value` エントリは RFC 3986 のパーセントエンコードが施されます**——予約文字を含む値が URL を壊したり注入したりできません。
* **エージェントがサポートしないユニバーサルマクロを持つパラメータは、丸ごとドロップされます**（そのキーは `dropped_params` に、マクロは `unmapped_macros` に報告されます）——エージェントが埋められないトラッカーを壊れたまま放出するより、省略する方が良いのです。ドロップされた同意/プライバシーマクロ（`{GDPR_CONSENT}`、`{US_PRIVACY}` など）は **`dropped_consent_macros`** にも表面化されます——忘れられたマッピングが同意の劣化したピクセルを黙って出荷しないよう、**検査してください**。
* **すでに発行済みのパラメータはそのまま通過します** — `pkg_id=123456`（マクロなし）はそのままにされます。
* **`suspect_native_values`** は、ネイティブトークンのような形（`%%…%%`、`{{…}}`、`${…}`、`[UPPER_SNAKE]`）を持つ `value` エントリをフラグします——ほぼ常に `native` のアームを使うべきだったマッピングです。
* クエリパラメータの**値**のみが変換されます。キー位置のマクロはそのままにされます。

### 4. インプレッション時

パブリッシャーのアドサーバーが残りのマクロを実際の値に置き換えます:

```
https://track.brand.com/imp?
  campaign=mb_spring_2025&
  device=ABC-123-DEF-456&
  cb=87654321
```

## ベストプラクティス

### マクロを一貫して使う

すべてのクリエイティブにわたって同じコアマクロの集合を含めます:

```
?buy={MEDIA_BUY_ID}&pkg={PACKAGE_ID}&cre={CREATIVE_ID}&cb={CACHEBUSTER}
```

これにより、トラッキングデータが一貫し、分析しやすくなります。

### フォーマットのサポートを確認する

どのマクロが利用可能かを確認するために、常に `list_creative_formats` を照会してください。すべてのフォーマットがすべてのマクロをサポートするわけではありません。

### VAST と AdCP マクロを組み合わせる

動画では、両方のシステムを併用します:

* **VAST マクロ** `[CACHEBUSTING]`、`[TIMESTAMP]` - 標準的な動画トラッキング向け
* **AdCP マクロ** `{MEDIA_BUY_ID}`、`{DEVICE_ID}` - あなたのキャンペーントラッキング向け

### プライバシーコンプライアンス

**重要**: クリエイティブのロジックで常にユーザーのプライバシー選択を尊重してください。

#### GDPR コンプライアンス（EU トラフィック）

EU で配信されるキャンペーン向け:

```javascript theme={null}
// Check consent before loading tracking
if (GDPR == 1) {
  if (GDPR_CONSENT && GDPR_CONSENT != '') {
    // User has consented - load tracking pixels
    loadTracking();
  } else {
    // No consent - skip tracking
    console.log('Tracking skipped - no GDPR consent');
  }
} else {
  // GDPR doesn't apply - load tracking
  loadTracking();
}
```

#### US Privacy / CCPA コンプライアンス

米国トラフィック向け:

```javascript theme={null}
// Check US Privacy string
if (US_PRIVACY == '1YYN') {
  // User has opted out - don't sell personal info
  skipPersonalizedTracking();
} else {
  // Load normal tracking
  loadTracking();
}
```

#### デバイスレベルのプライバシー

Limit Ad Tracking 設定を尊重します:

```javascript theme={null}
// Check if device ID is available
if (LIMIT_AD_TRACKING == 1 || DEVICE_ID == '' || DEVICE_ID == '00000000-0000-0000-0000-000000000000') {
  // User has limited tracking - use contextual attribution
  useContextualTracking();
} else {
  // Device ID available
  useDeviceTracking(DEVICE_ID);
}
```

#### プライバシーマクロの動作

**空の値**: プライバシー制限されたマクロは空文字列またはゼロを返します:

* `{DEVICE_ID}` → LAT が有効なときは `""` または `00000000-0000-0000-0000-000000000000`
* `{GDPR_CONSENT}` → 同意が提供されないときは `""`
* `{IP_ADDRESS}` → プライバシー制限時は `""` またはマスク/切り詰めされた IP

プライバシーに敏感なマクロを使う前に、**常に空の値をテスト**してください。

### URL エンコーディング

マクロのプレースホルダーを URL エンコードする必要はありません。アドサーバーが実際の値のエンコーディングを自動的に扱います。

**例**:

```
❌ WRONG: https://track.com/imp?device=%7BDEVICE_ID%7D
✅ CORRECT: https://track.com/imp?device={DEVICE_ID}
```

アドサーバーは、マクロを置き換えるときに実際の値を URL エンコードします。

### テンプレート構文

AdCP のマクロを持つ URL は、[RFC 6570 URI テンプレート（レベル 1）](https://datatracker.ietf.org/doc/html/rfc6570#section-1.2)として検証されます——単純な `{var}` 代入のみ。レベル 2〜4 の演算子（`{+SKU}`、`{#SKU}`、`{.SKU}`、`{/SKU}`、`{;SKU}`、`{?SKU}`、`{&SKU}`）は AdCP では**使われず**、マニフェストに現れてはなりません。アドサーバーは RFC 6570 の展開ではなく、リテラルな文字列置換を行います。

## セールスエージェント向けの実装ノート

*この節は AdCP の実装者向けであり、バイヤー向けではありません。*

### マクロ変換のアプローチ

セールスエージェントは、ユニバーサルマクロを自身のアドサーバーのネイティブ構文に変換しなければなりません。推奨されるアプローチ:

**オプション 1: トラフィッキング中にハードコード（MVP）**

* アドサーバーのクリエイティブを作成するとき、AdCP ID マクロを実際の値に置き換える
* プラットフォームマクロをアドサーバーの構文に変換する
* ラインアイテムごとに 1 つのクリエイティブを作成するが、シンプルで信頼できる

**オプション 2: ダイナミックラッパー（将来）**

* 広告コールを傍受し、値を動的に注入する
* より複雑だが、クリエイティブの重複を避ける

### 変換の例

**Google Ad Manager**:

```javascript theme={null}
{
  '{CACHEBUSTER}': '%%CACHEBUSTER%%',
  '{DEVICE_ID}': '%%ADVERTISING_IDENTIFIER_PLAIN%%',
  '{DEVICE_ID_TYPE}': '%%ADVERTISING_IDENTIFIER_TYPE%%',
  '{DOMAIN}': '%%SITE%%',
  '{VIDEO_ID}': '%%VIDEO_ID%%'
}
```

**Kevel**:

```javascript theme={null}
{
  '{CACHEBUSTER}': '{{timestamp}}',
  '{DEVICE_ID}': '{{device.ifa}}',
  '{DEVICE_ID_TYPE}': '{{device.ifaType}}',
  '{DOMAIN}': '{{request.domain}}'
}
```

**Xandr Monetize**:

```javascript theme={null}
{
  '{CACHEBUSTER}': '${CACHEBUSTER}',
  '{DEVICE_ID}': '${DEVICE_APPLE_IDA}',  // or ${DEVICE_AAID}
  '{DOMAIN}': '${DOMAIN}'
}
```

### クリックトラッカーの挿入

クリエイティブへのクリックは二つの別個のシグナルを生成し、AdCP はそれらを**別々のアセットスロット**としてモデル化します:

| スロット               | アセット                            | 役割                                             | OpenRTB Native の対応     |
| ------------------ | ------------------------------- | ---------------------------------------------- | ---------------------- |
| `landing_page_url` | `url`                           | ユーザーが遷移する単一の終端の宛先。                             | `link.url`             |
| `click_tracker`    | `pixel_tracker`（`event: click`） | クリック時にユーザーをそこへ遷移させ**ずに**発火する計測ホップ。任意の数だけ存在できる。 | `link.clicktrackers[]` |

この分離は IAB OpenRTB Native から継承されています: クリックは**ちょうど一つの宛先**と**N 個の fire-and-forget のクリックトラッカー**を持ちます（`link.fallback` のディープリンクは、その一つの宛先の代替形式であり、二つ目ではありません）。配信時にセールスエージェントはすべての `click_tracker` をカウントビーコンとして発火し、ユーザーを一つの `landing_page_url` へ遷移させます。両方のスロットは[アセットタイプ](/docs/creative/asset-types)で定義されています。

**マクロの挿入。** セールスエージェントは、プラットフォームがクリックを記録してユーザーを転送するよう、宛先の前に自身のアドサーバーのクリックトラッキングマクロを挿入します。宛先のエンコーディングはアドサーバー固有です（GAM は追記スタイルの `%%CLICK_URL_UNESC%%<landing>` を使い、他のサーバーは自己完結型の `?...&rurl=<encoded-landing>` 形式を提供します）:

**元のクリエイティブ**:

```html theme={null}
<a href="https://brand.com/product">Click here</a>
```

**挿入後（GAM）**:

```html theme={null}
<a href="%%CLICK_URL_UNESC%%https://brand.com/product">Click here</a>
```

**バイヤーのクリックスルーパラメータの保持。** クリックマクロの挿入は、バイヤー供給のクリックスルー URL にすでに存在するクエリパラメータ——エージェントが認識しないもの、例えばバイヤー側ベンダーのクリック識別子を含む——を剥ぎ取り、下流のアトリビューションを黙って壊す可能性があります。これらのパラメータを転送するエージェントは、バイヤーまたはサードパーティ供給のデータに由来する任意の値に、[代入安全性](#代入安全性カタログアイテムマクロ)がカタログアイテムの値に定義するエンコーディング規律（Unicode NFC 正規化、次に RFC 3986 の `unreserved` 集合へのパーセントエンコード）を適用するので、保持が URL コンテキストの抜け出し、CRLF 注入、bidi 偽装を再び開くことはありません。パラメータの保持を規範的な要件にするかどうかは、ワーキンググループのレビュー中のクリックトラッキング提案の一部です（[#5693](https://github.com/adcontextprotocol/adcp/issues/5693)）。

**バイヤーのクリック識別子をランディングに載せる。** `click_tracker` はカウントビーコンです: クリックを記録しますが、その識別子をユーザーのランディングセッションに置きません。ナビゲートされるのは `landing_page_url` だけだからです。バイヤーがクリック識別子をランディングに到達させる必要がある場合（クリックレベルのコンバージョンアトリビューションのため）、信頼できるリダイレクトなしのパターンは、その識別子をバイヤーが供給する `landing_page_url` に直接載せることです——リテラル値（`&buyer_click_id=abc123`）として、またはバイヤーが制御する AdCP マクロから構成して（`&buyer_click_id={CREATIVE_ID}`、配信時にセールスエージェントが展開）。`{buyer_click_id}` はそれ自体が AdCP マクロでは**ありません**——マクロ集合はクローズドなレジストリなので（[利用可能なマクロ](#フォーマット別に利用可能なマクロ)を参照）、バイヤーは新しいトークンではなく値を供給します。識別子は一つのナビゲートされる URL に乗るため、どの当事者のリダイレクトも終端ホップである必要がありません。これは、バイヤーが配信前に供給または導出できる任意の識別子で機能し、複数当事者のリダイレクトチェーンを完全に避けます。

クリック時に（ベンダー自身のリダイレクト内で）のみ発行できる識別子は、カウントビーコン上で生き残れず、その識別子が着地するようユーザーをベンダーのリダイレクトを*通じて*ルーティングするには、AdCP が定義しないチェーン契約が必要です。「このトラッカーはナビゲーションパス内になければならない」というバイヤーが宣言可能なスロットセマンティクスは、ワーキンググループで議論中です（[#5693](https://github.com/adcontextprotocol/adcp/issues/5693)）。それが着地するまで、カウントビーコンがデフォルトであり、パス内の識別子の生存はスコープ外です。

### マッピングの保存

照合のために、AdCP ID とアドサーバー ID の間のマッピングを保存します:

```javascript theme={null}
{
  media_buy_id: "mb_spring_2025",
  ad_server_order_id: "1234567",
  packages: [
    {
      package_id: "pkg_ctv_prime",
      ad_server_line_item_id: "8901234"
    }
  ]
}
```

これを `create_media_buy` のレスポンスで返し、照合のために照会可能にします。

## 関連ドキュメント

* [クリエイティブフォーマット](/docs/creative/formats) - フォーマット仕様と発見の理解
* [クリエイティブプロトコル](/docs/creative) - AdCP でクリエイティブがどう機能するか
