Skip to content

Commit 2a126fe

Browse files
authored
Enhance Reporting Documentation: Add Package Pricing Fields and add offline file delivery report example (#179)
* Doc: update schema for reporting, add offline file delivery examples * fix wrong report file extension in the offline delivery example path * feat: add csv example, remove naming convension on files
1 parent a8471c4 commit 2a126fe

File tree

3 files changed

+169
-10
lines changed

3 files changed

+169
-10
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
"adcontextprotocol": minor
3+
---
4+
5+
- Enhanced `get_media_buy_delivery` response to include package-level pricing information: `pricing_model`, `rate`, and `currency` fields added to `by_package` section.
6+
- Added offline file delivery examples for JSON Lines (JSONL), CSV, and Parquet formats.
7+
- Added tab structure to list different formats of offline delivery files in optimization reporting documentation.
8+
- Updated all delivery reporting examples to include new pricing fields.
9+
- Added comprehensive JSONL, CSV, and Parquet format examples with schema documentation.
10+
11+
**Impact:**
12+
- Buyers can now see pricing information directly in delivery reports for better cost analysis.
13+
- Publishers have clearer guidance on structured batch reporting formats that maintain nested data.
14+
- Documentation provides a detailed examples for implementing offline file delivery.
15+

docs/media-buy/media-buys/optimization-reporting.mdx

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Publishers can proactively push reporting data to buyers through webhook notific
7474
**Example: Offline Delivery**
7575
Publisher pushes daily report files to buyer's cloud storage:
7676
```
77-
s3://buyer-reports/publisher_name/2024/02/05/media_buy_delivery.json.gz
77+
s3://buyer-reports/publisher_name/2024/02/05/media_buy_delivery.jsonl.gz
7878
```
7979

8080
File contains same structure as webhook payload but aggregated across all campaigns. Buyer processes files on their schedule.
@@ -174,7 +174,7 @@ When a reporting webhook is configured, publishers commit to sending:
174174
- One final notification when the campaign completes
175175
- If reporting data is delayed beyond the expected delay window, a `"delayed"` notification will be sent
176176

177-
### Webhook Payload
177+
### Webhook Payload (Real-time)
178178

179179
Reporting webhooks use the same payload structure as [`get_media_buy_delivery`](/docs/media-buy/task-reference/get_media_buy_delivery) with additional metadata:
180180

@@ -211,6 +211,123 @@ Reporting webhooks use the same payload structure as [`get_media_buy_delivery`](
211211
- **`next_expected_at`**: ISO 8601 timestamp for next notification (omitted for final notifications)
212212
- **`media_buy_deliveries`**: Array of media buy delivery data (may contain multiple media buys aggregated by publisher)
213213

214+
### Offline File Delivery (Batch)
215+
216+
For offline file delivery, publishers can provide reporting data in JSON Lines (JSONL), CSV, or Parquet format. All formats preserve the nested JSON structure from webhook payloads, making them ideal for batch processing.
217+
218+
**Compression:**
219+
Files can be compressed with gzip (`.jsonl.gz`, `.csv.gz`, or `.parquet.gz`) for efficient storage and transfer. Compression is recommended for large files.
220+
221+
import Tabs from '@theme/Tabs';
222+
import TabItem from '@theme/TabItem';
223+
224+
<Tabs>
225+
<TabItem value="jsonl" label="JSONL" default>
226+
227+
---
228+
229+
**Structure:**
230+
231+
Each line in the JSONL file contains a complete webhook payload object. Multiple reports can be included by having multiple lines in the file. The structure matches the [webhook payload structure](#webhook-payload-real-time).
232+
233+
**Example:**
234+
235+
```jsonl
236+
{"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","buyer_ref":"campaign_a","status":"active","totals":{"impressions":125000,"spend":5625.00,"clicks":250,"ctr":0.002,"video_completions":87500,"completion_rate":0.70},"by_package":[{"package_id":"pkg_001","buyer_ref":"ctv_package","impressions":75000,"spend":3375.00,"clicks":150,"video_completions":52500,"pacing_index":0.95,"pricing_model":"cpcv","rate":0.045,"currency":"USD"},{"package_id":"pkg_002","buyer_ref":"audio_package","impressions":50000,"spend":2250.00,"clicks":100,"video_completions":35000,"pacing_index":0.93,"pricing_model":"cpm","rate":45.00,"currency":"USD"}]}]}
237+
{"notification_type":"scheduled","sequence_number":6,"next_expected_at":"2024-02-07T08:00:00Z","reporting_period":{"start":"2024-02-06T00:00:00Z","end":"2024-02-06T23:59:59Z"},"currency":"USD","media_buy_deliveries":[{"media_buy_id":"mb_002","buyer_ref":"campaign_b","status":"active","totals":{"impressions":200000,"spend":9000.00,"clicks":400,"ctr":0.002,"video_completions":140000,"completion_rate":0.70},"by_package":[{"package_id":"pkg_003","buyer_ref":"display_package","impressions":200000,"spend":9000.00,"clicks":400,"video_completions":140000,"pacing_index":1.02,"pricing_model":"cpm","rate":45.00,"currency":"USD"}]}]}
238+
```
239+
240+
**File Format:**
241+
- File extension: `.jsonl` or `.jsonl.gz` (compressed)
242+
- Compression: Consider using `.gz` compression for large files to reduce storage and transfer costs
243+
244+
---
245+
246+
</TabItem>
247+
<TabItem value="csv" label="CSV">
248+
249+
---
250+
251+
**Structure:**
252+
253+
CSV format flattens the nested JSON structure into rows. Since CSV cannot natively represent nested arrays, each child element (package) gets its own row with all parent-level data repeated. This is the standard approach for representing hierarchical data in CSV format.
254+
255+
```csv
256+
reporting_period.start,reporting_period.end,notification_type,sequence_number,next_expected_at,currency,media_buy_deliveries.media_buy_id,media_buy_deliveries.buyer_ref,media_buy_deliveries.status,media_buy_deliveries.totals.impressions,media_buy_deliveries.totals.spend,media_buy_deliveries.totals.clicks,media_buy_deliveries.totals.ctr,media_buy_deliveries.totals.video_completions,media_buy_deliveries.totals.completion_rate,by_package.package_id,by_package.buyer_ref,by_package.impressions,by_package.spend,by_package.clicks,by_package.video_completions,by_package.pacing_index,by_package.pricing_model,by_package.rate,by_package.currency
257+
```
258+
259+
**CSV Example:**
260+
261+
Each row represents a package with its parent media buy context repeated. Parent-level data (reporting period, media buy totals) is included in every package row:
262+
263+
```csv
264+
reporting_period.start,reporting_period.end,notification_type,sequence_number,next_expected_at,currency,media_buy_deliveries.media_buy_id,media_buy_deliveries.buyer_ref,media_buy_deliveries.status,media_buy_deliveries.totals.impressions,media_buy_deliveries.totals.spend,media_buy_deliveries.totals.clicks,media_buy_deliveries.totals.ctr,media_buy_deliveries.totals.video_completions,media_buy_deliveries.totals.completion_rate,by_package.package_id,by_package.buyer_ref,by_package.impressions,by_package.spend,by_package.clicks,by_package.video_completions,by_package.pacing_index,by_package.pricing_model,by_package.rate,by_package.currency
265+
2024-02-05T00:00:00Z,2024-02-05T23:59:59Z,scheduled,5,2024-02-06T08:00:00Z,USD,mb_001,campaign_a,active,125000,5625.00,250,0.002,87500,0.70,pkg_001,ctv_package,75000,3375.00,150,52500,0.95,cpcv,0.045,USD
266+
2024-02-05T00:00:00Z,2024-02-05T23:59:59Z,scheduled,5,2024-02-06T08:00:00Z,USD,mb_001,campaign_a,active,125000,5625.00,250,0.002,87500,0.70,pkg_002,audio_package,50000,2250.00,100,35000,0.93,cpm,45.00,USD
267+
2024-02-06T00:00:00Z,2024-02-06T23:59:59Z,scheduled,6,2024-02-07T08:00:00Z,USD,mb_002,campaign_b,active,200000,9000.00,400,0.002,140000,0.70,pkg_003,display_package,200000,9000.00,400,140000,1.02,cpm,45.00,USD
268+
```
269+
270+
---
271+
272+
</TabItem>
273+
<TabItem value="parquet" label="Parquet">
274+
275+
---
276+
277+
**Structure:**
278+
279+
Parquet files preserve the nested structure through nested columns. The schema mirrors the JSON structure:
280+
281+
**Schema Structure:**
282+
```
283+
reporting_period
284+
├── start (string)
285+
└── end (string)
286+
notification_type (string)
287+
sequence_number (int64)
288+
next_expected_at (string)
289+
currency (string)
290+
media_buy_deliveries (list)
291+
└── element (struct)
292+
├── media_buy_id (string)
293+
├── buyer_ref (string)
294+
├── status (string)
295+
├── totals (struct)
296+
│ ├── impressions (int64)
297+
│ ├── spend (double)
298+
│ ├── clicks (int64)
299+
│ ├── ctr (double)
300+
│ ├── video_completions (int64)
301+
│ └── completion_rate (double)
302+
└── by_package (list)
303+
└── element (struct)
304+
├── package_id (string)
305+
├── buyer_ref (string)
306+
├── impressions (int64)
307+
├── spend (double)
308+
├── clicks (int64)
309+
├── video_completions (int64)
310+
├── pacing_index (double)
311+
├── pricing_model (string)
312+
├── rate (double)
313+
└── currency (string)
314+
```
315+
316+
**Example Data Representation:**
317+
318+
The Parquet file contains the same data as the JSONL format, but stored in columnar format. For example:
319+
320+
| reporting_period.start | reporting_period.end | currency | media_buy_deliveries[0].media_buy_id | media_buy_deliveries[0].totals.impressions | media_buy_deliveries[0].by_package[0].package_id | media_buy_deliveries[0].by_package[0].pricing_model |
321+
|------------------------|----------------------|----------|---------------------------------------|-------------------------------------------|---------------------------------------------------|-----------------------------------------------------|
322+
| 2024-02-05T00:00:00Z | 2024-02-05T23:59:59Z | USD | mb_001 | 125000 | pkg_001 | cpcv |
323+
| 2024-02-05T00:00:00Z | 2024-02-05T23:59:59Z | USD | mb_001 | 125000 | pkg_002 | cpm |
324+
| 2024-02-06T00:00:00Z | 2024-02-06T23:59:59Z | USD | mb_002 | 200000 | pkg_003 | cpm |
325+
326+
---
327+
328+
</TabItem>
329+
</Tabs>
330+
214331
### Timezone Handling
215332

216333
**All reporting MUST use UTC.** This eliminates DST complexity, simplifies reconciliation, and ensures consistent 24-hour reporting periods.

docs/media-buy/task-reference/get_media_buy_delivery.mdx

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@ The message is returned differently in each protocol:
7474
"spend": "number",
7575
"clicks": "number",
7676
"video_completions": "number",
77-
"pacing_index": "number"
77+
"pacing_index": "number",
78+
"pricing_model": "string",
79+
"rate": "number",
80+
"currency": "string"
7881
}
7982
],
8083
"daily_breakdown": [
@@ -120,6 +123,9 @@ The message is returned differently in each protocol:
120123
- **clicks**: Package clicks
121124
- **video_completions**: Package video completions
122125
- **pacing_index**: Delivery pace (1.0 = on track, &lt;1.0 = behind, &gt;1.0 = ahead)
126+
- **pricing_model**: The pricing model used for this package (e.g., `"cpm"`, `"cpcv"`, `"cpp"`, `"cpc"`, `"cpv"`, `"vcpm"`, `"flat_rate"`). This indicates how the package is billed and which metrics are most relevant for optimization. See [Pricing Models](/docs/media-buy/advanced-topics/pricing-models) for details on each model.
127+
- **rate**: The pricing rate for this package in the specified currency. For fixed-rate pricing, this is the agreed rate (e.g., CPM rate of `12.50` means $12.50 per 1,000 impressions). For auction-based pricing, this represents the effective rate based on actual delivery. The rate helps calculate expected delivery and compare performance across different pricing models.
128+
- **currency**: ISO 4217 currency code (e.g., `"USD"`, `"EUR"`, `"GBP"`) for this specific package's pricing. This indicates the currency in which the `rate` and `spend` values are denominated. Different packages within the same media buy can use different currencies when supported by the publisher.
123129
- **daily_breakdown**: Day-by-day delivery
124130
- **date**: Date (YYYY-MM-DD)
125131
- **impressions**: Daily impressions
@@ -176,7 +182,10 @@ The AdCP payload is identical across protocols. Only the request/response wrappe
176182
"spend": 22500,
177183
"clicks": 0,
178184
"video_completions": 525000,
179-
"pacing_index": 0.95
185+
"pacing_index": 0.95,
186+
"pricing_model": "cpcv",
187+
"rate": 0.03,
188+
"currency": "USD"
180189
}
181190
]
182191
}
@@ -262,7 +271,10 @@ A2A returns results as artifacts:
262271
"spend": 22500,
263272
"clicks": 0,
264273
"video_completions": 525000,
265-
"pacing_index": 0.95
274+
"pacing_index": 0.95,
275+
"pricing_model": "cpcv",
276+
"rate": 0.03,
277+
"currency": "USD"
266278
}
267279
]
268280
}
@@ -330,14 +342,20 @@ A2A returns results as artifacts:
330342
"spend": 11250.00,
331343
"clicks": 500,
332344
"video_completions": 175000,
333-
"pacing_index": 0.93
345+
"pacing_index": 0.93,
346+
"pricing_model": "cpcv",
347+
"rate": 0.0643,
348+
"currency": "USD"
334349
},
335350
{
336351
"package_id": "pkg_audio_drive_ca_ny",
337352
"impressions": 200000,
338353
"spend": 5625.00,
339354
"clicks": 400,
340-
"pacing_index": 0.88
355+
"pacing_index": 0.88,
356+
"pricing_model": "cpm",
357+
"rate": 28.125,
358+
"currency": "USD"
341359
}
342360
],
343361
"daily_breakdown": [
@@ -410,7 +428,10 @@ A2A returns results as artifacts:
410428
"spend": 11250.00,
411429
"clicks": 500,
412430
"video_completions": 175000,
413-
"pacing_index": 0.93
431+
"pacing_index": 0.93,
432+
"pricing_model": "cpcv",
433+
"rate": 0.0643,
434+
"currency": "USD"
414435
}
415436
],
416437
"daily_breakdown": []
@@ -433,7 +454,10 @@ A2A returns results as artifacts:
433454
"spend": 5625.00,
434455
"clicks": 100,
435456
"video_completions": 56250,
436-
"pacing_index": 0.75
457+
"pacing_index": 0.75,
458+
"pricing_model": "cpm",
459+
"rate": 45.00,
460+
"currency": "USD"
437461
}
438462
],
439463
"daily_breakdown": []
@@ -456,7 +480,10 @@ A2A returns results as artifacts:
456480
"spend": 10000.00,
457481
"clicks": 400,
458482
"video_completions": 110000,
459-
"pacing_index": 1.05
483+
"pacing_index": 1.05,
484+
"pricing_model": "cpm",
485+
"rate": 33.33,
486+
"currency": "USD"
460487
}
461488
],
462489
"daily_breakdown": []

0 commit comments

Comments
 (0)