From 9447dd92ce4b9d095efb3e11b7807f16d99baf80 Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Sat, 2 May 2026 16:15:40 -0400 Subject: [PATCH] feat(schemas): delivery_measurement.vendors as BrandRef[] (closes #3860 BrandRef half) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces free-form provider string with structured vendors: BrandRef[] array. Deprecates the string for one minor. The merger question with performance_standards.vendor is deferred — they cover different scopes (overall measurement story vs committed-metrics with thresholds). Schema: - core/product.json delivery_measurement: adds vendors: BrandRef[], marks provider as deprecated, drops provider from required. Multiple BrandRefs because a single product often has multiple vendors in different roles (ad server + viewability vendor; retail-media seller + third-party retail measurement vendor). Doc: media-products.mdx field description shows the structured shape. Migration: existing provider strings work for one minor. New implementations populate vendors. Removed at next major. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../delivery-measurement-vendors-brandref.md | 38 +++++++++++++++++++ .../product-discovery/media-products.mdx | 2 +- static/schemas/source/core/product.json | 19 ++++++---- 3 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 .changeset/delivery-measurement-vendors-brandref.md diff --git a/.changeset/delivery-measurement-vendors-brandref.md b/.changeset/delivery-measurement-vendors-brandref.md new file mode 100644 index 0000000000..8ff85e7870 --- /dev/null +++ b/.changeset/delivery-measurement-vendors-brandref.md @@ -0,0 +1,38 @@ +--- +"adcontextprotocol": minor +--- + +Restructure `product.delivery_measurement.provider` as a `vendors: BrandRef[]` array, deprecating the legacy free-form string. Closes the BrandRef-migration half of #3860; the merger-with-`performance_standards` question is deferred to a follow-up RFC since it requires more design (`delivery_measurement` describes the *overall* measurement story while `performance_standards` carries *committed* metrics with thresholds — they're different concerns). + +**The BrandRef migration.** Before this minor, `delivery_measurement.provider` was a string like `"Google Ad Manager with IAS viewability"` — buyer agents had to string-parse to find the verification vendor. The string also conflated two jobs: vendor identity AND methodology description. With this minor: + +- New `vendors: BrandRef[]` field — structured measurement-vendor identity, anchored on `brand.json` `agents[type='measurement']`. Array because a single product often has multiple vendors playing different roles (ad server + viewability vendor; retail-media seller + third-party retail measurement). Each entry's measurement-agent capabilities catalog is queryable via `get_adcp_capabilities.measurement.metrics[]`. +- Legacy `provider: string` — marked deprecated. Dropped from the schema's `required` array (was previously the lone required field on `delivery_measurement`); retained for one-minor backwards compatibility. When both fields present, consumers MUST use `vendors` for identity and treat `provider` as informational text. +- `notes: string` — clarified as free-form methodology prose only, not vendor identification. + +**Distinct from `performance_standards.vendor`.** `delivery_measurement.vendors` carries vendor identity for the overall measurement story (including non-committed-but-reported metrics); `performance_standards[].vendor` carries vendor identity for *committed* metrics with thresholds. The two fields cover different scopes — the merger question raised in #3860 is deferred. + +**Migration.** + +```json +// before +"delivery_measurement": { + "provider": "Google Ad Manager with IAS viewability", + "notes": "MRC-accredited viewability. 50% in-view for 1s display / 2s video." +} + +// after +"delivery_measurement": { + "vendors": [ + { "domain": "googleadmanager.com" }, + { "domain": "integralads.com" } + ], + "notes": "MRC-accredited viewability. 50% in-view for 1s display / 2s video." +} +``` + +**Backwards compatibility.** Additive (new field, deprecated field retained, required dropped). Existing implementations populating `provider` continue to work for one minor; removed at the next major. + +**Doc updates.** `media-products.mdx` field description reflects the structured shape. + +Closes #3860 (BrandRef migration). The merger-with-`performance_standards` question stays open as a follow-up. diff --git a/docs/media-buy/product-discovery/media-products.mdx b/docs/media-buy/product-discovery/media-products.mdx index b49bb40958..31e4371ee8 100644 --- a/docs/media-buy/product-discovery/media-products.mdx +++ b/docs/media-buy/product-discovery/media-products.mdx @@ -26,7 +26,7 @@ Products declare which pricing models they support. Buyers select a specific pri - `delivery_type` (string, required): Either `"guaranteed"` or `"non_guaranteed"`. - `exclusivity` (string, optional): Whether this product offers exclusive access. `"none"` (default when absent) — multiple advertisers can buy simultaneously. `"category"` — one advertiser per industry category. `"exclusive"` — sole sponsorship. Most relevant for guaranteed products tied to specific shows or placements. - `pricing_options` (list[PricingOption], required): Array of available pricing models for this product. See [Pricing Models](#pricing-models). -- `delivery_measurement` (object, optional): Who measures ad delivery — the ad server and viewability vendor used to count impressions (e.g., "Google Ad Manager with IAS viewability"). When absent, buyers should apply their own measurement defaults. See [Delivery Measurement](#delivery-measurement). +- `delivery_measurement` (object, optional): Who measures ad delivery — the ad server and viewability vendor used to count impressions. New implementations populate `vendors` as a structured `BrandRef` array (e.g., `[{ "domain": "googleadmanager.com" }, { "domain": "integralads.com" }]`); the legacy `provider` string is deprecated. When absent, buyers should apply their own measurement defaults. See [Delivery Measurement](#delivery-measurement). - `outcome_measurement` (OutcomeMeasurement, **deprecated**): Legacy field for declaring business outcome measurement (lift, brand lift, foot traffic). New implementations declare outcome metrics via `reporting_capabilities.available_metrics` and pin attribution methodology + window via the `qualifier` slot on `committed_metrics`. Retained for one-minor backwards compatibility; removed at the next major. See [Commerce Media](/docs/media-buy/commerce-media) for the migration pattern. - `creative_policy` (CreativePolicy, optional): Creative requirements and restrictions. - `is_custom` (bool, optional): `true` if the product was generated for a specific brief. diff --git a/static/schemas/source/core/product.json b/static/schemas/source/core/product.json index 3251b65b7b..ff2dd83ab4 100644 --- a/static/schemas/source/core/product.json +++ b/static/schemas/source/core/product.json @@ -74,20 +74,25 @@ }, "delivery_measurement": { "type": "object", - "description": "Measurement provider and methodology for delivery metrics. The buyer accepts the declared provider as the source of truth for the buy. When absent, buyers should apply their own measurement defaults.", + "description": "Measurement vendors and methodology for delivery metrics. The buyer accepts the declared vendors as the source of truth for the buy. When absent, buyers should apply their own measurement defaults. Senders SHOULD populate `vendors` (structured BrandRef array) for new implementations; the legacy `provider` string field is deprecated and retained for one-minor backwards compatibility.", "properties": { + "vendors": { + "type": "array", + "description": "Measurement vendors used for this product, as structured `BrandRef` identities. Multiple entries when multiple vendors play different roles (e.g., the ad server plus a separate viewability vendor like IAS or DV; or a retail-media seller plus a third-party retail measurement vendor like Circana or NielsenIQ). Each vendor's `brand.json` `agents[type='measurement']` is the discovery anchor; metric definitions live on the agent's `get_adcp_capabilities.measurement.metrics[]` block. Distinct from `performance_standards[].vendor` which carries vendor identity for *committed* metrics with thresholds — this field carries vendor identity for the overall measurement story, including non-committed-but-reported metrics.", + "items": { + "$ref": "/schemas/core/brand-ref.json" + }, + "minItems": 1 + }, "provider": { "type": "string", - "description": "Measurement provider(s) used for this product (e.g., 'Google Ad Manager with IAS viewability', 'Nielsen DAR', 'Geopath for DOOH impressions')" + "description": "**Deprecated as of this minor.** Free-form measurement provider description (e.g., 'Google Ad Manager with IAS viewability', 'Nielsen DAR', 'Geopath for DOOH impressions'). New implementations SHOULD use the structured `vendors` field instead. Retained for one-minor backwards compatibility; removed at the next major. When both `vendors` and `provider` are present, consumers MUST use `vendors` for vendor identity and treat `provider` as informational text." }, "notes": { "type": "string", - "description": "Additional details about measurement methodology in plain language (e.g., 'MRC-accredited viewability. 50% in-view for 1s display / 2s video', 'Panel-based demographic measurement updated monthly')" + "description": "Additional details about measurement methodology in plain language (e.g., 'MRC-accredited viewability. 50% in-view for 1s display / 2s video', 'Panel-based demographic measurement updated monthly'). Free-form prose for context that doesn't fit the structured `vendors` field." } - }, - "required": [ - "provider" - ] + } }, "measurement_terms": { "$ref": "/schemas/core/measurement-terms.json",