Targeting-aware product discovery
AdCP 3.2 aligns targeting across discovery and purchase. Buyers provide concrete delivery constraints inlist_products.criteria.targeting_overlay or
request_proposals.criteria.targeting_overlay, and sellers return configured
products whose pricing and forecasts already account for those constraints.
get_products.targeting_overlay remains the compatibility-facade form.
What changed
- Split discovery tasks accept
criteria.targeting_overlay;get_productsaccepts the equivalent top-level field. - Proposal refinements can replace structured discovery criteria without restating inherited fields.
required_overlay_supportdeclares targeting dimensions whose values will be supplied on packages later.- Products declare selectable dimensions through
overlay_support. - Products disclose non-exact discovery alternatives through sparse
targeting_resolution.modifications. request_proposalsand theget_productscompatibility response confirm structured hard targeting inferred from natural-language briefs once through response-roottargeting_resolution.brief_targeting;refine_proposalsplaces confirmation in the affectedresults[]entry whenever that interpretation materially affects eligibility, pricing, or forecasting.- Product discovery and booked packages use lifecycle-specific schemas under
the shared
targeting_resolutionfield; demographic package execution moves totargeting_resolution.demographics. product_idis opaque. Non-custom wholesale IDs remain stable for the same logical offer within seller and declared cache scope; custom IDs are stable only within their issuing discovery/refinement lineage.placement_selectionjoins property and collection lists as purchased- inventory targeting inside the overlay.- Legacy targeting-like product filters are deprecated.
Filter migration
On split tasks, nest the replacements under
criteria and keep channel,
format, delivery type, pricing, reporting, and other product characteristics
in criteria.offer_filters. Legacy get_products keeps the flattened names
shown in the table for compatibility.
Briefs versus structured fields
Move any requirement with a structured AdCP representation out of prose and into that field. For targeting, this means usingtargeting_overlay. Structured
input is more compact, deterministic, and lossless. Briefs remain appropriate
for goals, context, semantic intent, preferences, and requirements without a
structured representation.
Hard targeting stated only in a brief remains binding. Sellers MUST expose the
predicate they inferred once as response-level
targeting_resolution.brief_targeting when that structured interpretation
materially affects product eligibility, pricing, or forecasting; otherwise it
remains a best practice. Do not use that field to echo an unchanged structured
overlay.
Known values versus future selection
Known values are real targeting and participate in forecasts:device_platform and device_platform_exclude are independently requested and
disclosed so exclusion support is never inferred from inclusion support.
Requirement true matches support true or any valid support object. An object
requirement matches support true or a support object containing every
requested boolean and array subset. Unrequested fields and numeric seller limits
do not participate. Support guarantees selectability, not inventory or a
value-specific forecast for every later selection. Rediscover with concrete
targeting_overlay values when that forecast is required. Fixed prices and
floors remain binding for supported selections; price guidance remains
non-binding.
ISO subdivision support follows the same split but can be country/value aware:
FR-49 constraint scopes the returned configured product and
forecast. The exclusion requirement is permission to select either candidate
later; it is not an availability promise for either value. Inclusion and
exclusion are matched independently. Numeric administrative depth is not used
because ISO subdivision categories are not uniform across countries.
Do not migrate raw ad-server keys
Do not replace legacy targeting-like filters with acustom,
key_value_pairs, or equivalent generic map. External buyers use typed AdCP
targeting fields, seller-published signal references, and structured inventory
selection. Sellers keep backend key/value compilation private. If a recurring
concept needs protocol support, standardize it as a typed field with explicit
matching and resolution behavior.
Accepting targeting modifications
Exact acceptance produces no structured-overlay echo. A product with no Producttargeting_resolution accepts the discovery overlay exactly, but does not
confirm how prose was interpreted. Brief-derived hard targeting may therefore
produce response-root targeting_resolution.brief_targeting on
request_proposals or get_products, or per-result confirmation on
refine_proposals, even when no overlay was sent.
An exact request-specific configured product issued through targeting-aware
discovery still returns is_custom: true and expires_at; absence of a
resolution echo does not make its price, forecast, or inventory assumptions
permanent. The generic Product schema continues accepting legacy custom
products without expires_at; the requirement belongs to this new discovery
flow and to every product that carries targeting_resolution.
A seller offering an alternative returns only the changed paths:
product_id in a direct create_media_buy, or accepting a finalized
proposal that purchases it, accepts the modification. A fresh unsupported
overlay sent directly at creation is still rejected; sellers never store a
knowingly non-equivalent package execution.
Product identity
Reuse non-custom wholesale IDs for the same logical offer within the seller and declaredcache_scope, including across reads and wholesale-feed webhooks.
Feed and pricing versions communicate mutation; retirement or replacement may
end the identity. A binding price, floor, currency, model, or priced
applicability change receives a new pricing_option_id; feed events do not
reinterpret an issued option ID. Do not extend wholesale ID stability to custom configured products.
Within the lineage that issued a custom ID, it remains stable for refinement
and purchase and identifies the complete buyable configuration, including
targeting resolution, forecast assumptions, and overlay support. The selected
(product_id, pricing_option_id) pair identifies its commercial terms.
The lineage is explicit in referenced product_id and proposal_id values,
not a transport session. On refine, top-level filters, targeting, and future
support replace prior values when present; omitted values remain bound through
the referenced product. Any changed buyable configuration receives a new ID.
Use the configured product_id throughout its discovery/refinement context.
Request-specific products carry expires_at. A seller that still recognizes an
expired ID returns PRODUCT_EXPIRED; after its expiry tombstone is no longer
retained, or when the ID belongs to another account or lineage,
PRODUCT_NOT_FOUND applies. Sellers do not retain tombstones indefinitely and
do not reveal cross-tenant existence through the error choice. Either result requires rediscovery. This
change deliberately does not introduce a second “catalog product” identity that
could be confused with AdCP creative catalogs.
Placement selection
Placement selection is purchased-inventory targeting:creative_assignments[].placement_refs route a creative only within the
already-purchased set. Placement selection is a complete set: products with
fixed mode: included placements use the product default and do not advertise
selectable placement support. Placement, property, and collection changes all
use the existing update_targeting action.
A selected placement set exactly equal to the product’s complete fixed
mode: included set is an inherent restatement across discovery, create, and
update. It does not require overlay_support.placement_selection; partial
selection still requires a selectable product.
This placement lifecycle supersedes the separate top-level selection proposed
in issue #6132. It is
nested in targeting_overlay so purchased inventory follows the same
discovery, forecasting, authorization, and readback rules as other targeting.
There is no separate update_placements action: a seller advertises
update_targeting, and an unavailable action is rejected with
ACTION_NOT_ALLOWED and attempted_action: "update_targeting".
On update_media_buy, omission has two different meanings:
- Omit
targeting_overlayto leave all targeting unchanged. - Supply
targeting_overlayas the complete desired post-update overlay. Omittingplacement_selectionfrom that replacement removes the prior placement constraint; it does not preserve that nested field.
INVALID_REQUEST; unsupported selection returns UNSUPPORTED_FEATURE; and a
selection outside the priced envelope returns REQUOTE_REQUIRED. Every
rejection leaves the prior package targeting and assignments unchanged.
Compatibility window
Release negotiation is the coarse feature gate. There is no separatetargeting_aware_discovery capability flag: a seller advertising a 3.2 release
is promising the 3.2 discovery contract, while each product’s overlay_support
remains authoritative for the dimensions that can be selected later.
Before sending targeting_overlay or required_overlay_support, a buyer:
- Reads
get_adcp_capabilities.adcp.supported_versions. - Selects a compatible 3.2 release or prerelease and sends that exact
release-precision value in
adcp_version(plusadcp_major_version: 3through 3.x). - Validates the response against the echoed
adcp_version.
supported_versions, or a list whose highest compatible release is
3.1 or earlier, is not evidence of targeting-aware discovery. The buyer must
omit the 3.2 fields and use legacy targeting filters or explicit brief prose.
It must not optimistically send unknown fields to a major-only seller because a
legacy implementation may accept and ignore them through an open schema.
A 3.2 seller receiving a 3.1 pin either serves the 3.1 schema and omits 3.2-only
request/response semantics, or returns VERSION_UNSUPPORTED when it does not
support 3.1. It never labels a 3.2-shaped response as 3.1.
Sellers may translate a legacy targeting filter into its overlay equivalent.
When a 3.2 request contains both forms, the seller accepts them only when they
are semantically identical; conflicting forms are rejected with
INVALID_REQUEST as ambiguous. Legacy-only requests remain supported through
3.x.
Schema surfaces are available through the v3 alias: