Skip to main content
データドリブンな監視と最適化による継続的改善を実現します。AdCP はパフォーマンス追跡・配信分析・成果向上を支援する包括的なレポーティング/最適化機能を提供します。 AdCP のレポーティングはキャンペーン設定に用いる Targeting と整合しており、ライフサイクル全体で一貫した分析が可能です。ターゲットした内容と同じ粒度でレポートできます。 パフォーマンスデータは AdCP の Accountability & Trust Framework に反映され、パブリッシャーは安定した配信でレピュテーションを築き、バイヤーはデータに基づいて配分判断ができます。

主な最適化タスク

デリバリーレポート

get_media_buy_delivery でインプレッション、消化額、クリック、コンバージョンなど全パッケージのパフォーマンスデータを取得します。 あるいはメディアバイ作成時に Webhook ベースのレポーティング を設定し、定期的な自動通知を受け取ります。

キャンペーン更新

パフォーマンスインサイトに基づき、update_media_buy で設定・予算・構成を更新します。

最適化ワークフロー

一般的な最適化サイクル:
  1. 配信を監視: 目標に対するパフォーマンスを追跡
  2. パフォーマンス分析: 最適化の機会を特定
  3. 調整を実施: 予算・ターゲティング・クリエイティブ割り当てを更新
  4. 変化を追跡: 最適化の影響をモニタリング
  5. 反復: 定期的な分析で継続的改善

パフォーマンス監視

リアルタイム指標

配信中のキャンペーンを追跡します。
  • 目標に対する インプレッション配信状況
  • 予算に対する 消化ペース
  • CTR とエンゲージメント
  • 事業成果に紐づく コンバージョン追跡

ヒストリカル分析

時間軸でパフォーマンス傾向を把握します。
  • 主要指標の 日次/時間別の内訳
  • 期間をまたいだ パフォーマンス比較
  • 最適化機会を見つける トレンド識別

アラート/通知

重要なキャンペーンイベントを把握します。
  • ペース異常に対する 配信アラート
  • 大きな変化に対する パフォーマンス通知
  • 上限到達前の 予算警告

配信方法

パブリッシャーは Webhook 通知またはオフラインファイル配信でレポートデータをバイヤーへプッシュできます。これによりポーリングを不要にし、タイムリーなインサイトを提供します。 Webhook Push(リアルタイム) - バイヤーのエンドポイントへ HTTP POST
  • 適合: 多くのバイヤー・セラー関係
  • レイテンシ: ほぼリアルタイム(秒〜分)
  • コスト: 標準的な Webhook 基盤
オフラインファイル配信(バッチ) - クラウドストレージバケットへのプッシュ
  • 適合: 高ボリュームの大口バイヤー/セラー
  • レイテンシ: 定期バッチ(毎時/日次)
  • コスト: 大幅に低い(0.010.10/GB0.01-0.10/GB 対 0.50-2.00/100 万 Webhook)
  • フォーマット: JSON Lines, CSV, Parquet
  • ストレージ: S3, GCS, Azure Blob Storage

Webhook ベースのレポーティング

Webhook 設定

メディアバイ作成時に reporting_webhook パラメーターでレポート Webhook を設定します。
{
  "packages": [...],
  "reporting_webhook": {
    "url": "https://buyer.example.com/webhooks/reporting",
    "authentication": {
      "schemes": ["Bearer"],
      "credentials": "secret_token_min_32_chars"
    },
    "reporting_frequency": "daily"
  }
}
本番推奨: HMAC 署名付き
{
  "packages": [...],
  "reporting_webhook": {
    "url": "https://buyer.example.com/webhooks/reporting",
    "authentication": {
      "schemes": ["HMAC-SHA256"],
      "credentials": "shared_secret_min_32_chars"
    },
    "reporting_frequency": "daily"
  }
}
セキュリティ必須:
  • authentication 設定は必須(32 文字以上)
  • Bearer トークン: シンプルで開発向き(Authorization ヘッダー)
  • HMAC-SHA256: 本番推奨。リプレイ攻撃を防止(署名ヘッダー)
  • 資格情報はオンボーディング時に帯域外で交換
  • 実装詳細は Security を参照

サポートされる頻度

パブリッシャーはプロダクトの reporting_capabilities でサポートする頻度を宣言します。すべてをサポートする必要はなく、運用に適した頻度を選択します。
  • hourly: キャンペーン期間中、毎時間通知(任意。コスト/複雑性を考慮)
  • daily: 1 日 1 回通知(最も一般的、フェーズ1に推奨)
  • monthly: 月 1 回通知(タイムゾーンはパブリッシャー指定)
コスト考慮: 時間単位 Webhook は日次の 24 倍のトラフィックを発生。大規模なバイヤー/セラーではコスト効率のためオフラインレポートを好む場合があります。

提供可能な指標

指標の可否は 2 つのレベルで宣言します。
  1. プロダクトレベル: reporting_capabilities.available_metrics でプラットフォームが提供できる指標を宣言
  2. フォーマットレベル: クリエイティブフォーマットの reported_metrics でそのフォーマットが生成できる指標を宣言(Reported Metrics を参照)
バイヤーは両者の積集合を受け取ります。impressionsspend は積集合によらず常に提供されます。標準的な指標:
  • impressions: 広告表示(常に提供)
  • spend: 消化額(常に提供)
  • clicks: クリック数
  • ctr: クリック率
  • views: プラットフォーム定義の閾値での視聴数
  • completed_views: 動画 100% 完了数
  • video_completions: 動画視聴完了数
  • completion_rate: 動画完了率
  • conversions: クリック後/視聴後コンバージョン
  • conversion_value: 帰属コンバージョンの金銭的価値
  • roas: 広告費用対効果
  • cost_per_acquisition: コンバージョンあたりコスト
  • leads: リード獲得数
  • reach: ユニークリーチ
  • frequency: 個人あたり平均フリクエンシー
  • grps: グロスレーティングポイント(CPP 課金向け)
  • viewability: ビューアビリティデータ(measurable_impressions, viewable_impressions, viewable_rate, standard)。MRC 基準と GroupM 基準を区別
  • engagement_rate: プラットフォーム固有のエンゲージメント指標
  • quartile_data: 動画クォータイル完了データ(q1〜q4)
  • dooh_metrics: DOOH 固有指標(ループ再生数、スクリーン数、会場別内訳)
  • cost_per_click: クリックあたりコスト
バイヤーは requested_metrics で必要な指標のみを要求し、ペイロードを抑えて KPI に集中できます。

パブリッシャーのコミットメント

レポート Webhook を設定した場合、パブリッシャーは以下を送信します。 (campaign_duration / reporting_frequency) + 1 回の通知
  • キャンペーン期間中、頻度ごとに 1 回
  • キャンペーン完了時に最終通知を 1 回
  • 想定遅延時間を超える場合は "delayed" 通知を送信

Webhook ペイロード

レポート Webhook は get_media_buy_delivery と同じペイロードにメタデータを加えます。
{
  "notification_type": "scheduled",
  "sequence_number": 5,
  "next_expected_at": "2024-02-06T08:00:00Z",
  "reporting_period": {
    "start": "2024-02-05T00:00:00Z",
    "end": "2024-02-05T23:59:59Z"
  },
  "currency": "USD",
  "media_buy_deliveries": [
    {
      "media_buy_id": "mb_001",
      "status": "active",
      "totals": {
        "impressions": 125000,
        "spend": 5625.00,
        "clicks": 250,
        "ctr": 0.002
      },
      "by_package": [...]
    }
  ]
}
Fields:
  • notification_type: "scheduled"(定期)、"final"(完了)、"delayed"(データ未準備)
  • sequence_number: 連番(1 起算)
  • next_expected_at: 次回通知の ISO 8601 時刻(最終通知では省略)
  • media_buy_deliveries: メディアバイ配信データの配列(パブリッシャーが複数メディアバイをまとめて返す場合あり)

タイムゾーンの扱い

レポーティングはすべて UTC を使用しなければなりません。 DST の複雑性を排除し、照合を簡素化し、一貫した 24 時間単位を保証します。
{
  "reporting_capabilities": {
    "timezone": "UTC",
    "available_reporting_frequencies": ["daily"],
    "date_range_support": "date_range"
  }
}
レポート期間:
  • 日次: 00:00:00Z 〜 23:59:59Z(常に 24 時間)
  • 時次: 時刻 00 分 00 秒〜59 分 59 秒(常に 1 時間)
  • 月次: 月初〜月末
Example webhook payload:
{
  "reporting_period": {
    "start": "2024-02-05T00:00:00Z",
    "end": "2024-02-05T23:59:59Z"
  }
}

遅延レポーティング

プロダクトの expected_delay_minutes 内にレポートデータが用意できない場合、パブリッシャーは notification_type: "delayed" で通知します。
{
  "notification_type": "delayed",
  "sequence_number": 3,
  "next_expected_at": "2024-02-06T10:00:00Z",
  "message": "Reporting data delayed due to upstream processing. Expected availability in 2 hours."
}
これにより、通知が欠落したと誤解されるのを防ぎます。

Webhook の集約

複数のメディアバイが以下を共有する場合、呼び出し数削減のため Webhook を集約すべきです。
  • 同一 Webhook URL
  • 同一のレポート頻度
  • 同一のレポート期間
: バイヤーが同一エンドポイントで日次レポートを受けるアクティブキャンペーンを 100 件持つ場合
  • 集約なし: 1 日 100 件の Webhook(非効率)
  • 集約あり: 1 日 1 件の Webhook に 100 キャンペーンをまとめる(最適)
media_buy_deliveries 配列には Webhook 1 件あたり 1〜N のメディアバイが含まれます。バイヤーは配列を反復して各キャンペーンを処理してください。 Aggregated webhook example:
{
  "notification_type": "scheduled",
  "reporting_period": {
    "start": "2024-02-05T00:00:00Z",
    "end": "2024-02-05T23:59:59Z"
  },
  "currency": "USD",
  "media_buy_deliveries": [
    { "media_buy_id": "mb_001", "totals": { "impressions": 50000, "spend": 1750 }, ... },
    { "media_buy_id": "mb_002", "totals": { "impressions": 48500, "spend": 1695 }, ... },
    // ... 98 more media buys
  ]
}
バイヤーは配列を反復し、各メディアバイを個別に処理します。集計値が必要な場合は各メディアバイの合計から算出してください。

部分的な失敗の扱い

複数メディアバイを 1 つの Webhook にまとめる際、キャンペーンごとにデータ可否が異なる場合があります。 方針: ステータス付きベストエフォート配信 パブリッシャーは利用可能なデータをすべて含めた集約 Webhook を送り、ステータスで可否を示すべきです。
{
  "notification_type": "scheduled",
  "sequence_number": 5,
  "reporting_period": {
    "start": "2024-02-05T00:00:00Z",
    "end": "2024-02-05T23:59:59Z"
  },
  "currency": "USD",
  "media_buy_deliveries": [
    {
      "media_buy_id": "mb_001",
      "status": "active",
      "totals": {
        "impressions": 50000,
        "spend": 1750
      }
    },
    {
      "media_buy_id": "mb_002",
      "status": "active",
      "totals": {
        "impressions": 48500,
        "spend": 1695
      }
    },
    {
      "media_buy_id": "mb_003",
      "status": "reporting_delayed",
      "message": "Reporting data temporarily unavailable for this campaign",
      "expected_availability": "2024-02-06T02:00:00Z"
    }
  ],
  "partial_data": true,
  "unavailable_count": 1
}
部分失敗の主なフィールド:
  • partial_data: いずれかのキャンペーンでデータ欠落がある場合に true
  • unavailable_count: 遅延/欠落しているキャンペーン数
  • status: キャンペーン単位のステータス("active", "reporting_delayed", "failed"
  • expected_availability: 遅延データの準備予定時刻(分かる場合)
部分配信を使うべきケース:
  1. 上流遅延: データソースの速度差があります
  2. システム劣化: 部分的な障害が一部キャンペーンに影響
  3. データ品質問題: 特定キャンペーンのみ検証に失敗
  4. レートリミット: API 制限で全キャンペーンを取得できません
部分配信を使わないケース:
  1. 全体障害: "delayed" 通知を送る
  2. 全キャンペーンに影響: notification_type: "delayed" を使用
  3. バイヤー側エンドポイント問題: サーキットブレーカーで送信を止める
バイヤー側の処理例:
function processAggregatedWebhook(webhook) {
  if (webhook.partial_data) {
    console.warn(`Partial data: ${webhook.unavailable_count} campaigns delayed`);
  }

  for (const delivery of webhook.media_buy_deliveries) {
    if (delivery.status === 'reporting_delayed') {
      // Mark campaign as pending, retry via polling or wait for next webhook
      markCampaignPending(delivery.media_buy_id, delivery.expected_availability);
    } else if (delivery.status === 'active') {
      // Process normal delivery data
      processCampaignMetrics(delivery);
    } else {
      console.error(`Unexpected status for ${delivery.media_buy_id}: ${delivery.status}`);
    }
  }
}
ベストプラクティス:
  • データがない場合もステータス付きで全キャンペーンを配列に含めます
  • 遅延/失敗がある場合は partial_data: true を設定
  • 分かる場合は expected_availability を返す
  • Webhook 全体をリトライしません。必要ならバイヤーは個別にポーリング
  • 部分配信率をモニタリングし、システム的な問題を検知

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

GDPR/CCPA 向けの PII マスキング
パブリッシャーはすべての Webhook ペイロードから PII を削除し、GDPR/CCPA に準拠しなければなりません。レポート Webhook には集計・匿名化された指標のみを含めてください。 除去するもの:
  • ユーザー ID、デバイス ID、IP アドレス
  • メールアドレス、電話番号
  • 正確な位置情報(緯度/経度)
  • Cookie ID、広告 ID(集計されていない場合)
  • PII を含むカスタムディメンション
保持してよいもの:
  • 集計指標(インプレッション、消化額、クリックなど)
  • 粗い地理情報(市/州/国。番地は不可)
  • デバイスタイプカテゴリ(モバイル/デスクトップ/タブレット)
  • ブラウザ/OS カテゴリ
  • 時間ベースの集計
Example - Before PII Scrubbing (❌ DO NOT SEND):
{
  "media_buy_id": "mb_001",
  "user_events": [
    {
      "user_id": "user_12345",
      "ip_address": "192.168.1.100",
      "device_id": "abc-def-ghi",
      "impressions": 1,
      "lat": 40.7128,
      "lon": -74.0060
    }
  ]
}
Example - After PII Scrubbing (✅ CORRECT):
{
  "media_buy_id": "mb_001",
  "totals": {
    "impressions": 125000,
    "spend": 5625.00,
    "clicks": 250
  },
  "by_package": [
    {
      "package_id": "pkg_001",
      "impressions": 125000,
      "spend": 5625.00,
      "by_geo": [
        {
          "geo_level": "region",
          "geo_code": "US-NY",
          "geo_name": "New York",
          "impressions": 45000,
          "spend": 2025.00
        }
      ],
      "by_geo_truncated": false
    }
  ]
}
パブリッシャーの責任:
  • Webhook 配信ではなくデータ収集レイヤーで PII をマスクします
  • 再識別されないよう集計閾値を設定(例: セグメントあたり 10 ユーザー以上)
  • 収集データと Webhook で共有するデータの違いを明文化
  • GDPR 準拠のため DPA(データ処理契約)を提供
  • GDPR/CCPA の削除依頼に対応
バイヤーの責任:
  • requested_metrics やカスタムディメンションで PII を要求しません
  • Webhook データが集計・匿名化されていることを理解します
  • 適切なデータ保持ポリシーを実装
  • プライバシーポリシー/ユーザー通知に Webhook データを含めます

実装ベストプラクティス

  1. 配列を扱う: 1 件でも media_buy_deliveries は配列として処理します
  2. 冪等なハンドラー: 重複通知を安全に処理(Webhook は at-least-once 配信)
  3. シーケンス管理: sequence_number で欠落/順不同の通知を検知
  4. フォールバックポーリング: Webhook 失敗時に備え定期ポーリングを継続
  5. タイムゾーン意識: 期間計算のためパブリッシャーのタイムゾーンを保持
  6. 頻度の検証: リクエストした頻度が available_reporting_frequencies に含まれることを確認
  7. 指標の検証: リクエストした指標が available_metrics に含まれることを確認
  8. PII コンプライアンス: Webhook ペイロードにユーザーレベルデータを含めない

Webhook Health Monitoring

Webhook 配信ステータスは AdCP のグローバルタスク管理システム で追跡します(Task Lifecycle 参照)。 reporting_webhook を設定してメディアバイを作成すると、パブリッシャーは配信用のタスクを生成します。バイヤーは標準のタスククエリで Webhook の健全性を監視できます。 タスク管理を使う利点:
  • すべての AdCP オペレーションで一貫したステータス管理
  • ポーリング/Webhook の標準パターンを利用
  • ステータス/履歴/エラーの既存インフラを活用
  • メディアバイ固有の健全性エンドポイントが不要
Webhook 配信が恒常的に失敗しサーキットブレーカーが開いた場合、パブリッシャーはタスクステータスを更新して問題を示します。バイヤーは通常のタスク監視で検知できます。

オフラインファイル配信ベースのレポーティング

例: オフライン配信 パブリッシャーが日次レポートをバイヤーのクラウドストレージへプッシュ:
s3://buyer-reports/publisher_name/2024/02/05/media_buy_delivery.json.gz
ファイルは Webhook と同じ構造で、すべてのキャンペーンを集約しています。バイヤーは都合の良いタイミングで処理します。 オフライン配信を使うケース:
  • 同一バイヤーで 100 本超のアクティブキャンペーン
  • 時間単位レポートが必要(コスト 24 倍削減)
  • 詳細な内訳や多次元データでボリュームが大きい
  • バイヤーにバッチ処理基盤があります
パブリッシャーはプロダクトの capabilities でオフライン配信サポートを宣言します。
{
  "reporting_capabilities": {
    "supports_webhooks": true,
    "supports_offline_delivery": true,
    "offline_delivery_protocols": ["s3", "gcs"],
    "date_range_support": "date_range"
  }
}
オフライン配信では JSON Lines (JSONL)、CSV、Parquet でレポートを提供できます。いずれも Webhook のネスト構造を保つためバッチ処理に適しています。 .jsonl.gz/.csv.gz/.parquet.gz のように gzip 圧縮してストレージと転送コストを削減できます。

JSON Lines (JSONL)

1 行 1 メディアバイ(改行区切り JSON)。各行にレポート期間とパッケージレベルのデータを持つ 1 つのデリバリーオブジェクトが含まれます。ネスト構造を保持しつつ、行単位で簡単にパースできるためストリーミング処理に適しています。 Example JSONL file:
{"notification_type": "scheduled", "sequence_number": 5, "next_expected_at": "2024-02-06T08:00:00Z", "reporting_period": {"start": "2024-02-05T00:00:00Z", "end": "2024-02-05T23:59:59Z"}, "currency": "USD", "media_buy_id": "mb_001", "media_buy_id": "campaign_a", "status": "active", "totals": {"impressions": 50000, "spend": 1750.00, "clicks": 100, "ctr": 0.002}, "by_package": [{"package_id": "pkg_001", "impressions": 30000, "spend": 1050.00, "pacing_index": 0.95, "pricing_model": "cpm", "rate": 0.035, "currency": "USD"}, {"package_id": "pkg_002", "impressions": 20000, "spend": 700.00, "pacing_index": 0.98, "pricing_model": "cpm", "rate": 0.035, "currency": "USD"}]}
{"notification_type": "scheduled", "sequence_number": 5, "next_expected_at": "2024-02-06T08:00:00Z", "reporting_period": {"start": "2024-02-05T00:00:00Z", "end": "2024-02-05T23:59:59Z"}, "currency": "USD", "media_buy_id": "mb_002", "media_buy_id": "campaign_b", "status": "active", "totals": {"impressions": 200000, "spend": 9000.00, "clicks": 400, "ctr": 0.002}, "by_package": [{"package_id": "pkg_003", "impressions": 200000, "spend": 9000.00, "pacing_index": 1.02, "pricing_model": "cpm", "rate": 45.00, "currency": "USD"}]}
{"notification_type": "scheduled", "sequence_number": 5, "next_expected_at": "2024-02-06T08:00:00Z", "reporting_period": {"start": "2024-02-05T00:00:00Z", "end": "2024-02-05T23:59:59Z"}, "currency": "USD", "media_buy_id": "mb_003", "media_buy_id": "campaign_c", "status": "active", "totals": {"impressions": 75000, "spend": 3375.00, "clicks": 150, "ctr": 0.002}, "by_package": [{"package_id": "pkg_004", "impressions": 75000, "spend": 3375.00, "pacing_index": 0.96, "pricing_model": "cpcv", "rate": 0.045, "currency": "USD"}]}

CSV

For tabular analysis CSV files require unnesting nested arrays. Each record should be unnested to the by_package level, meaning one row per package with parent-level data (reporting period, media buy info, totals) duplicated. Example CSV structure:
notification_type,sequence_number,next_expected_at,reporting_period_start,reporting_period_end,currency,media_buy_id,media_buy_id,status,totals_impressions,totals_spend,totals_clicks,totals_ctr,by_package_package_id,by_package_impressions,by_package_spend,by_package_clicks,by_package_pacing_index,by_package_pricing_model,by_package_rate,by_package_currency
scheduled,5,2024-02-06T08:00:00Z,2024-02-05T00:00:00Z,2024-02-05T23:59:59Z,USD,mb_001,campaign_a,active,50000,1750.00,100,0.002,pkg_001,30000,1050.00,60,0.95,cpm,0.035,USD
scheduled,5,2024-02-06T08:00:00Z,2024-02-05T00:00:00Z,2024-02-05T23:59:59Z,USD,mb_001,campaign_a,active,50000,1750.00,100,0.002,pkg_002,20000,700.00,40,0.98,cpm,0.035,USD
scheduled,5,2024-02-06T08:00:00Z,2024-02-05T00:00:00Z,2024-02-05T23:59:59Z,USD,mb_002,campaign_b,active,200000,9000.00,400,0.002,pkg_003,200000,9000.00,400,1.02,cpm,45.00,USD
scheduled,5,2024-02-06T08:00:00Z,2024-02-05T00:00:00Z,2024-02-05T23:59:59Z,USD,mb_003,campaign_c,active,75000,3375.00,150,0.002,pkg_004,75000,3375.00,150,0.96,cpcv,0.045,USD

Parquet

For high-volume analytics Columnar format optimized for analytics workloads. Excellent compression ratios. Supports nested structures natively. Best for data warehouses and big data processing. Example Parquet schema:
{
  "type": "record",
  "name": "MediaBuyDelivery",
  "fields": [
    {"name": "notification_type", "type": "string"},
    {"name": "sequence_number", "type": "int"},
    {"name": "next_expected_at", "type": "string"},
    {"name": "reporting_period", "type": {
      "type": "record",
      "name": "ReportingPeriod",
      "fields": [
        {"name": "start", "type": "string"},
        {"name": "end", "type": "string"}
      ]
    }},
    {"name": "currency", "type": "string"},
    {"name": "media_buy_id", "type": "string"},
    {"name": "media_buy_id", "type": "string"},
    {"name": "status", "type": "string"},
    {"name": "totals", "type": {
      "type": "record",
      "name": "Totals",
      "fields": [
        {"name": "impressions", "type": "long"},
        {"name": "spend", "type": "double"},
        {"name": "clicks", "type": "long"},
        {"name": "ctr", "type": "double"}
      ]
    }},
    {"name": "by_package", "type": {
      "type": "array",
      "items": {
        "type": "record",
        "name": "PackageDelivery",
        "fields": [
          {"name": "package_id", "type": "string"},
          {"name": "impressions", "type": "long"},
          {"name": "spend", "type": "double"},
          {"name": "pacing_index", "type": "double"},
          {"name": "pricing_model", "type": "string"},
          {"name": "rate", "type": "double"},
          {"name": "currency", "type": "string"}
        ]
      }
    }}
  ]
}
File Structure: Each file contains one media buy delivery per line (JSONL) or row (CSV/Parquet). Files may contain:
  • Multiple media buy deliveries (one per line/row)
  • Multiple reporting periods for the same media buy (separate rows)
  • Multiple media buys (each with its own rows)
Processing Recommendations:
  • Process files in chronological order using file timestamps
  • Handle duplicate files gracefully (idempotent processing)
  • Validate file integrity using checksums if provided
  • Monitor for missing files and alert on gaps

Data Reconciliation

get_media_buy_delivery API はレポート配信手段(Webhook/オフラインファイル/ポーリング)によらず、すべてのキャンペーン指標の正式な信頼できる唯一の情報源です。 照合は あらゆるレポート配信方法 で重要です。
  • Webhooks: ネットワーク障害やサーキットブレーカーで欠落する場合があります
  • オフラインファイル: 遅延・破損・処理失敗の可能性があります
  • ポーリング: API 障害中にデータを欠損する場合があります
  • 遅延データ: 初回レポートから 24〜48 時間以上後に届くインプレッションがある(全手段共通)

Reconciliation Process

バイヤーは定期的に配信データを API と照合し、精度を確認すべきです。 Recommended Reconciliation Schedule:
  • Hourly delivery: Reconcile via API daily
  • Daily delivery: Reconcile via API weekly
  • Monthly delivery: Reconcile via API at month end + 7 days
  • Campaign close: Always reconcile after campaign_end + attribution_window
Reconciliation Logic:
async function reconcileWebhookData(mediaBuyId, startDate, endDate) {
  // Get authoritative data from API
  const apiData = await adcp.getMediaBuyDelivery({
    media_buy_id: mediaBuyId,
    date_range: { start: startDate, end: endDate }
  });

  // Compare with webhook data in local database
  const webhookData = await db.getWebhookTotals(mediaBuyId, startDate, endDate);

  const discrepancy = {
    impressions: apiData.totals.impressions - webhookData.impressions,
    spend: apiData.totals.spend - webhookData.spend,
    clicks: apiData.totals.clicks - webhookData.clicks
  };

  // Acceptable discrepancy thresholds
  const impressionVariance = Math.abs(discrepancy.impressions) / apiData.totals.impressions;
  const spendVariance = Math.abs(discrepancy.spend) / apiData.totals.spend;

  if (impressionVariance > 0.02 || spendVariance > 0.01) {
    // Significant discrepancy (>2% impressions or >1% spend)
    console.warn(`Reconciliation discrepancy for ${mediaBuyId}:`, discrepancy);

    // Update local database with authoritative API data
    await db.updateCampaignTotals(mediaBuyId, apiData.totals);

    // Alert if discrepancy is unusually large
    if (impressionVariance > 0.10 || spendVariance > 0.05) {
      await alertOps(`Large reconciliation discrepancy detected`, {
        media_buy_id: mediaBuyId,
        webhook_totals: webhookData,
        api_totals: apiData.totals,
        discrepancy
      });
    }
  }

  return {
    status: impressionVariance < 0.02 ? 'reconciled' : 'discrepancy_found',
    api_data: apiData.totals,
    webhook_data: webhookData,
    discrepancy
  };
}
Why Discrepancies Occur:
  1. Delivery failures: Webhooks missed, offline files corrupted, API timeouts during polling
  2. Late-arriving data: Impressions attributed after initial reporting (all delivery methods)
  3. Data corrections: Publisher adjusts metrics after initial reporting
  4. Processing errors: Buyer-side failures to process delivered data
  5. Timezone differences: Period boundaries may differ between delivery and API query
Source of Truth Rules:
  • For billing: Always use get_media_buy_delivery API at campaign end + attribution window
  • For real-time decisions: Use delivered data (webhook/file/poll) for speed, reconcile later
  • For discrepancies: API data wins, update local records accordingly
  • For audits: API provides complete historical data, delivered data is ephemeral
Best Practices:
  • Store webhook sequence_number to detect missed notifications
  • Run automated reconciliation daily for active campaigns
  • Alert on discrepancies >2% for impressions or >1% for spend
  • Use API data for all financial reporting and invoicing
  • Document reconciliation process for audit compliance

Late-Arriving Impressions

Ad serving data often arrives with delays due to attribution windows, offline tracking, and pipeline latency. Publishers declare expected_delay_minutes in reporting_capabilities:
  • Display/Video: Typically 4-6 hours
  • Audio: Typically 8-12 hours
  • CTV: May be 24+ hours
This represents when most data is available, not all data.

遅延データの扱い

過去の期間に遅延データが届いた場合、その期間を is_adjusted: true 付きで 再送 します。
{
  "notification_type": "adjusted",
  "reporting_period": {
    "start": "2024-02-01T00:00:00Z",
    "end": "2024-02-01T23:59:59Z"
  },
  "media_buy_deliveries": [{
    "media_buy_id": "mb_001",
    "is_adjusted": true,
    "totals": {
      "impressions": 51000,  // Updated total (was 50000)
      "spend": 1785          // Updated spend (was 1750)
    }
  }]
}
バイヤー側の処理:
function processWebhook(webhook) {
  for (const delivery of webhook.media_buy_deliveries) {
    if (delivery.is_adjusted) {
      // Replace entire period with updated totals
      db.replaceCampaignPeriod(
        delivery.media_buy_id,
        webhook.reporting_period,
        delivery.totals
      );
    } else {
      // Normal new period data
      db.insertCampaignPeriod(delivery.media_buy_id, webhook.reporting_period, delivery.totals);
    }
  }
}
調整済み期間を送るべき場合:
  • 大きなデータ変化(インプレッション ±2% 超、または消化額 ±1% 超)
  • campaign_end + attribution_window 時点での最終照合
  • データ品質修正
ポーリングのみの場合、バイヤーは API 結果を時系列で比較することで調整を検知します。

Webhook の信頼性

レポート Webhook は AdCP 標準の信頼性パターンに従います。
  • At-least-once 配信: 同じ通知が複数回届く場合があります
  • ベストエフォート順序: 順不同で届く場合があります
  • タイムアウトとリトライ: 配信失敗時は回数を限定して再試行
実装の詳細は Webhooks を参照してください。

最適化の戦略

コンバージョン最適化

メディアバイパッケージに最適化目標を設定することで、特定の成果(目標 CPC、CPV、ROAS、CPA など)に向けた配信を促します。指標目標(クリック、視聴数)はイベント設定不要で機能します。イベント目標にはイベントソースの設定とコンバージョンデータが必要です。 完全なセットアップ手順は Conversion Tracking を、optimization_goals 配列のリファレンスは Optimization Goals を参照してください。

予算最適化

  • update_media_buy で成果の高低パッケージ間での 再配分
  • ペーシング調整evenasapfront_loaded の配信方式を切り替え
  • 消化効率 — パッケージ間でのコンバージョンあたりコストを比較し、優れたパッケージへ予算をシフト

クリエイティブ最適化

  • get_media_buy_delivery でクリエイティブ別の内訳を使った パフォーマンス分析
  • A/B テストcreative_assignments でウェイト付き複数クリエイティブを割り当て
  • リフレッシュ戦略sync_creatives でクリエイティブを交換し疲弊を防止

ターゲティング改善

  • 地理的最適化 — 地域別配信データに基づき targeting_overlay を調整
  • フリクエンシー管理 — 配信パターンに基づき frequency_cap(クールダウン抑制または max_impressions/per/window 上限)をチューニング

パフォーマンスフィードバックループ

ビジネス成果をパブリッシャーにフィードバックすることで、AI 主導の最適化を可能にします。詳細な API は provide_performance_feedback を参照してください。

パフォーマンスインデックスの概念

相対的な成果を示す正規化スコア。
  • 0.0 = 測定可能な価値や影響なし
  • 1.0 = ベースライン/想定パフォーマンス
  • > 1.0 = 平均以上(例: 1.45 は 45% 改善)
  • < 1.0 = 平均未満(例: 0.8 は 20% 低下)

パフォーマンスデータの共有

バイヤーは provide_performance_feedback タスクを使って任意で成果を共有できます。
{
  "media_buy_id": "gam_1234567890",
  "measurement_period": {
    "start": "2024-01-15T00:00:00Z",
    "end": "2024-01-21T23:59:59Z"
  },
  "performance_index": 1.35,
  "metric_type": "conversion_rate"
}

サポートされる指標

  • overall_performance: キャンペーン全体の成果
  • conversion_rate: クリック後/視聴後コンバージョン率
  • brand_lift: ブランド認知/想起のリフト
  • click_through_rate: クリエイティブのエンゲージメント
  • completion_rate: 動画/音声の完了率
  • viewability: ビューアブル率
  • brand_safety: ブランドセーフティ順守
  • cost_efficiency: 望む成果あたりのコスト

パブリッシャーが活用する方法

パブリッシャーはパフォーマンスインデックスを活用して:
  1. 配信最適化: 高成果セグメントへ配信をシフト
  2. 価格調整: 実証された価値に基づき CPM を更新
  3. プロダクト改善: 成果パターンに基づきプロダクト定義を磨く
  4. アルゴリズム強化: 実際のビジネス成果で ML モデルを学習

プライバシーとデータ共有

  • パフォーマンス共有は任意でありバイヤーが制御します
  • 集計されたパフォーマンス傾向はプラットフォーム全体の改善に利用される場合があります
  • 個別キャンペーンの詳細はバイヤーとパブリッシャーの関係内に留まる

ディメンション内訳

配信データは各パッケージ内で複数のディメンションに分解できます。バイヤーは get_media_buy_deliveryreporting_dimensions パラメーターで特定の内訳を指定します。各内訳は by_package 項目内に by_* 配列として現れ、by_creative と同じ構成パターンに従います。
ディメンション内訳フィールド主なフィールドケイパビリティフラグ
地理by_geogeo_level, geo_code, geo_namesupports_geo_breakdown(オブジェクト — 利用可能なレベル/システムを宣言)
デバイスタイプby_device_typedevice_typesupports_device_type_breakdown
デバイスプラットフォームby_device_platformdevice_platformsupports_device_platform_breakdown
オーディエンスby_audienceaudience_id, audience_source, audience_namesupports_audience_breakdown
プレースメントby_placementplacement_id, placement_namesupports_placement_breakdown
各内訳エントリは delivery-metrics(インプレッション、消化額、クリック、コンバージョンなど)のすべてのフィールドに加え、ディメンション固有の識別フィールドを持ちます。各エントリには最低限、識別子、impressionsspend が必要です。 内訳はオプトイン方式で、明示的に指定しない限りディメンションデータは返されません。指定したディメンションをサポートしていないセラーはそれを黙って省略します。各内訳配列には limit を超える追加行の有無を示す by_*_truncated ブール値が付属します。

ターゲティングの一貫性

レポーティングは AdCP の Targeting アプローチに沿って設計されており、以下を可能にします。
  • キャンペーンライフサイクル全体での 一貫した分析
  • ターゲティングパラメーターによる きめ細かい内訳
  • ポートフォリオ最適化のための キャンペーン横断インサイト

Target → Measure → Optimize

ターゲティングとレポーティングの一貫性が好循環を生み出します。
  1. Target: ブリーフとオーバーレイでオーディエンスを定義(例:「主要都市圏のモバイルユーザー」)
  2. Measure: 同じ属性でレポート(デバイスタイプと地域別のパフォーマンスを追跡)
  3. Optimize: 配信改善にパフォーマンスをフィードバック(高成果セグメントへ予算をシフト)

標準指標

すべてのプラットフォームがサポートしなければなりませんコア指標:
  • impressions: 広告表示数
  • spend: 通貨建て消化額
  • clicks: クリック数(該当する場合)
  • ctr: クリック率(clicks/impressions)
任意のオプション指標:
  • conversions: クリック後/視聴後コンバージョン
  • viewability: ビューアブルインプレッションの割合
  • completion_rate: 動画/音声の完了率
  • engagement_rate: プラットフォーム固有のエンゲージメント指標

プラットフォーム固有の考慮事項

プラットフォームによってレポーティング/最適化の機能は異なります。
  • 包括的なディメンション別レポーティング、リアルタイム/ヒストリカルデータ、高度なビューアビリティ指標

Kevel

  • リアルタイムレポーティング API、カスタム指標サポート、柔軟な集計オプション

Triton Digital

  • 音声固有指標(完了率、スキップ率)、局別パフォーマンスデータ、デイパート分析

高度な分析

キャンペーン横断分析

  • 複数キャンペーンにまたがる ポートフォリオパフォーマンス
  • オーディエンスオーバーラップ とフリクエンシー管理
  • キャンペーン間の 予算配分 最適化

予測インサイト

  • ヒストリカルデータに基づく パフォーマンス予測
  • AI 分析による 最適化レコメンデーション
  • プロアクティブな調整のための トレンド予測

レスポンスタイム

最適化オペレーションには予測可能なタイミングがあります。
  • デリバリーレポート: 約 60 秒(データ集計)
  • キャンペーン更新: 分〜日単位(変更内容による)
  • パフォーマンス分析: 約 1 秒(キャッシュ済み指標)

ベストプラクティス

  1. 頻繁にレポートする: 定期的なレポーティングが最適化機会を増やす
  2. ペーシングを追跡する: 目標に対する配信を監視し、過不足を防ぐ
  3. パターンを分析する: ディメンション横断でパフォーマンストレンドを探す
  4. レイテンシを考慮する: 一部の指標には帰属遅延がある場合があります
  5. 指標を正規化する: パフォーマンス比較に一貫したベースラインを使用します

メディアバイライフサイクルとの統合

最適化/レポーティングはアクティブなキャンペーン全期間を通じて継続するフェーズです。
  • 作成との連携: 学習を活かして将来のキャンペーン設定を改善
  • 更新の指針: キャンペーン変更のためのデータドリブンな意思決定
  • スケールの実現: 実証された戦略を類似キャンペーンへ展開
  • AI へのフィード: パフォーマンスデータが自動最適化を向上

関連ドキュメント