From fac8bca1e5f1cc4985cfadf210af961c92f8798b Mon Sep 17 00:00:00 2001 From: Brian O'Kelley Date: Thu, 28 May 2026 19:07:21 -0400 Subject: [PATCH] feat: add video placement type filters --- .changeset/video-placement-types.md | 5 +++++ .../product-discovery/media-products.mdx | 17 +++++++++++++++++ .../media-buy/task-reference/get_products.mdx | 2 ++ .../source/core/placement-definition.json | 9 +++++++++ static/schemas/source/core/placement.json | 9 +++++++++ .../schemas/source/core/product-filters.json | 10 ++++++++++ static/schemas/source/core/product.json | 9 +++++++++ .../source/enums/video-placement-type.json | 19 +++++++++++++++++++ static/schemas/source/index.json | 4 ++++ .../media-buy/get-products-request.json | 1 + 10 files changed, 85 insertions(+) create mode 100644 .changeset/video-placement-types.md create mode 100644 static/schemas/source/enums/video-placement-type.json diff --git a/.changeset/video-placement-types.md b/.changeset/video-placement-types.md new file mode 100644 index 0000000000..cfce042d53 --- /dev/null +++ b/.changeset/video-placement-types.md @@ -0,0 +1,5 @@ +--- +"adcontextprotocol": minor +--- + +Add `video_placement_types` declarations to products and placements, plus a matching `get_products.filters.video_placement_types` discovery filter, using IAB Tech Lab/OpenRTB 2.6 video placement definitions with AdCP-native field names. diff --git a/docs/media-buy/product-discovery/media-products.mdx b/docs/media-buy/product-discovery/media-products.mdx index cbe58e2034..19669279d8 100644 --- a/docs/media-buy/product-discovery/media-products.mdx +++ b/docs/media-buy/product-discovery/media-products.mdx @@ -19,6 +19,7 @@ Products declare which pricing models they support. Buyers select a specific pri - `description` (string, required) - `publisher_properties` (list[PublisherPropertySelector], required): Publisher properties covered by this product. See [Property Targeting](#property-targeting). - `channels` (list[string], optional): Advertising channels this product is sold as (e.g., `["retail_media"]`, `["display", "olv"]`). Sellers SHOULD declare `channels` on products that span non-obvious channels, particularly retail media, CTV/OLV, and multi-channel bundles. Product channels SHOULD be a subset of the union of their properties' `supported_channels`. See [Media Channel Taxonomy](/docs/reference/media-channel-taxonomy). +- `video_placement_types` (list[string], optional): Declared video placement types that may be included in this product, using IAB Tech Lab/OpenRTB 2.6 `video.plcmt` definitions with AdCP-native names: `instream`, `accompanying_content`, `interstitial`, and `standalone`. Aggregate products and ad-network products may include multiple values. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context. - `format_ids` (list[FormatID], conditional): Legacy named-format references. Products must include `format_ids`, `format_options`, or both. See [Creative Formats](/docs/creative/formats). - `format_options` (list[ProductFormatDeclaration], conditional): 3.1+ canonical format-option declarations accepted by this product. Buyers prefer `format_options` when both format fields are present. Product-level formats are the upper bound for the sellable product; placement-level formats can narrow this set but cannot add formats the product does not accept. Buyer `FormatOptionRef` selectors use `{scope: "publisher", publisher_domain, format_option_id}` for publisher-declared options and `{scope: "product", format_option_id}` for product-local options. - `placements` (list[Placement], optional): Specific public ad placements within this product. Each placement declares `kind` (`publisher_ref` or `seller_inline`) and `mode` (`targetable` or `included`); seller-private delivery objects are not exposed here. See [Placements](#placements). @@ -194,6 +195,7 @@ Products can optionally declare specific public ad placements within their inven - **`placement_id`** - Placement ID in the publisher namespace. Buyers reference it with `publisher_domain` in `creative_assignments[].placement_refs`; legacy `placement_ids` strings are only unambiguous in single-publisher contexts. - **`mode: "targetable"`** - The buyer may reference this publisher-scoped placement when assigning creatives or otherwise selecting placements within the product - **`mode: "included"`** - The public placement is part of the product's described composition, but the buyer cannot cherry-pick it by `placement_id` +- **`video_placement_types`** - Declared video placement types for OLV and other video placements. Concrete placements usually declare one value; aggregate placements may declare multiple. - **Publisher reference rule** - Publisher-referenced product placements resolve to `{publisher_domain, placement_id}` in the publisher's `adagents.json` - **Private inventory rule** - Seller-private delivery objects, ad-server mappings, and source/origin details must stay out of `get_products` - **Creative assignment** - Different creatives can be assigned to targetable placements @@ -206,6 +208,21 @@ Products can optionally declare specific public ad placements within their inven Publishers can authorize agents for specific placements in `adagents.json` with `authorized_agents[].placement_ids` or `authorized_agents[].placement_tags`. Sales agents should only return publisher-referenced placements they are authorized to sell. +#### Video placement types + +Video products can declare `video_placement_types` at the product level, placement level, or both. The vocabulary follows the IAB Tech Lab/OpenRTB 2.6 `video.plcmt` definitions, but AdCP uses readable field and value names rather than the OpenRTB wire name: + +| Value | Meaning | +|---|---| +| `instream` | Video ads before, during, or after streaming video content requested by the user | +| `accompanying_content` | Video ads in a player with accompanying video content associated with the page or app content | +| `interstitial` | Video ads shown as an interstitial experience, typically between content or app states | +| `standalone` | Video ads shown without associated video content, also called no-content or standalone video | + +The field is an array because a sellable product can aggregate multiple placement types. For example, an OLV network product might include both `instream` and `accompanying_content`, while individual targetable placements narrow to one type. When both product and placement declarations are present, the product-level array should be the union of the video placement types the seller may deliver under that product. + +This is a discovery signal, not a verification claim. Buyers can filter for products that can satisfy a requested type with `get_products.filters.video_placement_types`, but sellers should not return mixed, non-targetable bundles for an instream-only filter unless they can constrain delivery to instream inventory during planning or purchase. + #### Format precedence with placements Product-level `format_ids` and `format_options` define the creative formats accepted by the product as a whole. Placement-level `format_ids` or `format_options`, whether returned inline on the product placement or inherited from a public publisher placement declaration, only narrow that product-wide set for the specific placement. diff --git a/docs/media-buy/task-reference/get_products.mdx b/docs/media-buy/task-reference/get_products.mdx index 402709d287..594fad28a1 100644 --- a/docs/media-buy/task-reference/get_products.mdx +++ b/docs/media-buy/task-reference/get_products.mdx @@ -174,6 +174,7 @@ The seller must declare `features.property_list_filtering: true` in [`get_adcp_c | `regions` | string[] | Filter by region coverage using ISO 3166-2 codes (e.g., `["US-NY", "GB-SCT"]`). Best for locally-bound inventory | | `metros` | object[] | Filter by metro coverage. Each entry: `{ system, code }` (e.g., `[{ "system": "nielsen_dma", "code": "501" }]`) | | `channels` | string[] | Filter by advertising channels (e.g., `["display", "ctv", "social", "streaming_audio"]`). See [Media Channel Taxonomy](/docs/reference/media-channel-taxonomy) | +| `video_placement_types` | string[] | Filter video products by acceptable declared video placement types: `instream`, `accompanying_content`, `interstitial`, or `standalone`. Sellers should return only products they can satisfy with at least one requested type, and should exclude mixed, non-targetable bundles unless delivery can be constrained to the requested type. Uses IAB Tech Lab/OpenRTB 2.6 `video.plcmt` definitions with AdCP-native names. | | `postal_areas` | object[] | Filter by postal area coverage. Each entry: `{ system, values }` (e.g., `[{ "system": "us_zip", "values": ["10001"] }]`) | | `geo_proximity` | object[] | Filter by proximity to geographic points. Each entry uses exactly one boundary method: `radius`, `travel_time` + `transport_mode`, or `geometry` | | `keywords` | object[] | Filter by keyword relevance for search/retail media. Each entry: `{ keyword, match_type? }`. `match_type` defaults to `broad` if omitted | @@ -193,6 +194,7 @@ Each returned placement may carry: | `placement_id` | Placement identifier in the publisher namespace. Buyers reference this with `publisher_domain` in `creative_assignments[].placement_refs`; legacy `placement_ids` strings are only unambiguous in single-publisher contexts. | | `publisher_domain` | Domain whose `adagents.json` defines the publisher-referenced placement. New multi-publisher products SHOULD include it. When omitted on legacy products, buyers may interpret `placement_id` relative to the seller agent's own publisher domain. | | `mode` | `targetable` means the buyer may reference the publisher-scoped placement, for example in `creative_assignments[].placement_refs`. `included` means the placement is part of the product composition but not buyer-selectable. | +| `video_placement_types` | Declared video placement types for OLV and other video inventory, using the IAB Tech Lab/OpenRTB 2.6 `video.plcmt` definitions with AdCP-native names. Concrete placements usually declare one value; aggregate placements may declare multiple. | | `format_ids` / `format_options` | Placement-specific creative support. Product-level formats are the upper bound; placement-level formats narrow the effective accepted set for that placement and must not add formats the product does not accept. | Publishers can authorize sales agents for specific publisher placements using `authorized_agents[].placement_ids` or `authorized_agents[].placement_tags` in `adagents.json`. Sellers should only return publisher-referenced placements they are authorized to sell. diff --git a/static/schemas/source/core/placement-definition.json b/static/schemas/source/core/placement-definition.json index cac60b5f8c..02e850ac36 100644 --- a/static/schemas/source/core/placement-definition.json +++ b/static/schemas/source/core/placement-definition.json @@ -85,6 +85,15 @@ }, "minItems": 1 }, + "video_placement_types": { + "type": "array", + "description": "Declared video placement types for this publisher placement, using IAB Tech Lab/OpenRTB 2.6 video.plcmt definitions with AdCP-native names. Most concrete placements SHOULD declare a single value; aggregate placements MAY declare multiple values. Product-level placement declarations may narrow this set but SHOULD NOT broaden it. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.", + "items": { + "$ref": "/schemas/enums/video-placement-type.json" + }, + "uniqueItems": true, + "minItems": 1 + }, "ext": { "$ref": "/schemas/core/ext.json" } diff --git a/static/schemas/source/core/placement.json b/static/schemas/source/core/placement.json index 828e532a56..ea46946a8b 100644 --- a/static/schemas/source/core/placement.json +++ b/static/schemas/source/core/placement.json @@ -56,6 +56,15 @@ "$ref": "/schemas/core/product-format-declaration.json" }, "minItems": 1 + }, + "video_placement_types": { + "type": "array", + "description": "Declared video placement types for this product placement, using IAB Tech Lab/OpenRTB 2.6 video.plcmt definitions with AdCP-native names. Most concrete placements SHOULD declare a single value; aggregate placements MAY declare multiple values. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.", + "items": { + "$ref": "/schemas/enums/video-placement-type.json" + }, + "uniqueItems": true, + "minItems": 1 } }, "required": [ diff --git a/static/schemas/source/core/product-filters.json b/static/schemas/source/core/product-filters.json index 00c0a44d69..dc04b901a0 100644 --- a/static/schemas/source/core/product-filters.json +++ b/static/schemas/source/core/product-filters.json @@ -126,6 +126,16 @@ }, "minItems": 1 }, + "video_placement_types": { + "type": "array", + "description": "Filter video products by acceptable declared video placement types, using IAB Tech Lab/OpenRTB 2.6 video.plcmt definitions with AdCP-native names. Sellers SHOULD return only products they can satisfy with at least one requested type. Products whose only available delivery is a mixed, non-targetable bundle that includes unrequested video placement types SHOULD NOT match unless the seller can constrain delivery to the requested type during planning or purchase. This filter has set semantics for wholesale feed canonicalization.", + "items": { + "$ref": "/schemas/enums/video-placement-type.json" + }, + "uniqueItems": true, + "minItems": 1, + "x-canonicalization": "set" + }, "required_axe_integrations": { "type": "array", "description": "Deprecated: Use trusted_match filter instead. Filter to products executable through specific agentic ad exchanges. URLs are canonical identifiers.", diff --git a/static/schemas/source/core/product.json b/static/schemas/source/core/product.json index 7b933c0b89..9b46f04dac 100644 --- a/static/schemas/source/core/product.json +++ b/static/schemas/source/core/product.json @@ -60,6 +60,15 @@ }, "minItems": 1 }, + "video_placement_types": { + "type": "array", + "description": "Declared video placement types that may be included in this product, using IAB Tech Lab/OpenRTB 2.6 video.plcmt definitions with AdCP-native names. Use on OLV, CTV, and other video products when buyers need to distinguish instream, accompanying-content, interstitial, and standalone/no-content inventory. Aggregate products and ad-network products MAY declare multiple values. When `placements[]` also carry `video_placement_types`, this product-level array SHOULD be the union of the placement-level declarations the seller may deliver under the product. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.", + "items": { + "$ref": "/schemas/enums/video-placement-type.json" + }, + "uniqueItems": true, + "minItems": 1 + }, "delivery_type": { "$ref": "/schemas/enums/delivery-type.json" }, diff --git a/static/schemas/source/enums/video-placement-type.json b/static/schemas/source/enums/video-placement-type.json new file mode 100644 index 0000000000..808ffeac26 --- /dev/null +++ b/static/schemas/source/enums/video-placement-type.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "/schemas/enums/video-placement-type.json", + "title": "Video Placement Type", + "description": "Declared video placement classification for OLV and other video inventory, using the IAB Tech Lab/OpenRTB 2.6 video.plcmt definitions with AdCP-native value names. This is seller-declared discovery metadata, not independent verification of inventory quality or delivery context.", + "type": "string", + "enum": [ + "instream", + "accompanying_content", + "interstitial", + "standalone" + ], + "enumDescriptions": { + "instream": "OpenRTB 2.6 video.plcmt=1: video ads played before, during, or after streaming video content requested by the user.", + "accompanying_content": "OpenRTB 2.6 video.plcmt=2: video ads played with accompanying video content in a player associated with the page or app content.", + "interstitial": "OpenRTB 2.6 video.plcmt=3: video ads shown as an interstitial experience, typically between content or app states.", + "standalone": "OpenRTB 2.6 video.plcmt=4: video ads shown without associated video content, also called no-content or standalone video." + } +} diff --git a/static/schemas/source/index.json b/static/schemas/source/index.json index 228ef0dcb2..829a94b9d9 100644 --- a/static/schemas/source/index.json +++ b/static/schemas/source/index.json @@ -608,6 +608,10 @@ "$ref": "/schemas/enums/channels.json", "description": "Advertising channels (display, video, dooh, ctv, audio, etc.)" }, + "video-placement-type": { + "$ref": "/schemas/enums/video-placement-type.json", + "description": "Declared video placement classifications using IAB Tech Lab/OpenRTB 2.6 video.plcmt definitions" + }, "task-status": { "$ref": "/schemas/enums/task-status.json", "description": "Standardized task status values based on A2A TaskState enum" diff --git a/static/schemas/source/media-buy/get-products-request.json b/static/schemas/source/media-buy/get-products-request.json index 8d823ba097..689973cdac 100644 --- a/static/schemas/source/media-buy/get-products-request.json +++ b/static/schemas/source/media-buy/get-products-request.json @@ -190,6 +190,7 @@ "description", "publisher_properties", "channels", + "video_placement_types", "format_ids", "format_options", "placements",