Background
The audience-targeting capability today describes what kinds of identifiers a seller accepts (supported_identifier_types, supported_uid_types, supports_platform_customer_id) but says nothing about how the data moves. AdCP-native sync, TMP identity match, cloud bucket dropoff, vendor-mediated dataset queries, clean room matches — these are the integration realities that determine whether activation is one config switch or three weeks of engineering work for a buyer.
The gap
A buyer with a Snowflake-based audience pipeline and a seller that only takes direct-API audience sync are technically compatible (both speak sync_audiences) and practically incompatible without rebuilding the buyer's pipeline. Today this is discovered at integration time, or worse, at activation time when a campaign starts and audiences don't sync.
Today's nearest fields:
audience_targeting.supported_identifier_types — kinds of IDs (email, phone).
audience_targeting.supported_uid_types — UID frameworks (RampID, UID2, MAID).
audience_targeting.supports_platform_customer_id — platform-native customer IDs.
None answer "where does the data move and how."
Proposed addition
A new audience_activation block on core/product.json and a supported_activation_methods summary on the audience_targeting capability. Each activation method declares a pattern plus pattern-specific fields. Two patterns are AdCP-canonical and first-class; three cover non-AdCP integration realities.
AdCP-canonical patterns (preferred)
sync_audiences — bare. Seller declares "I accept audience pushes via the AdCP sync_audiences tool." Any AdCP-speaking buyer can use it.
tmp_identity_match — declares specific buyer agents the seller integrates with for TMP runtime identity match. Seller must list each buyer agent it has configured. The integration isn't generic; the seller has set up TMP calls to specific buyer agents.
{ "pattern": "sync_audiences" }
{ "pattern": "tmp_identity_match", "buyer_agent": { "agent_url": "https://buyer.scope3.com" } }
{ "pattern": "tmp_identity_match", "buyer_agent": { "agent_url": "https://buyer.interchange.com" } }
Non-AdCP patterns (legacy / vendor-specific)
cloud_bucket — raw cloud storage push or pull. Requires direction and cloud_provider (a BrandRef).
{ "pattern": "cloud_bucket", "direction": "push_to_seller", "cloud_provider": { "domain": "amazon.com" } }
{ "pattern": "cloud_bucket", "direction": "pull_from_buyer", "cloud_provider": { "domain": "amazon.com" } }
{ "pattern": "cloud_bucket", "direction": "push_to_seller", "cloud_provider": { "domain": "cloud.google.com" } }
direction is push_to_seller (buyer writes to seller-hosted bucket) or pull_from_buyer (seller reads from buyer-hosted bucket). These have different security/legal posture and aren't interchangeable.
dataset_query — vendor-mediated query access (Snowflake Secure Data Sharing, Databricks Delta Sharing, BigQuery authorized views). Seller queries a dataset the buyer makes available through the vendor's sharing mechanism. Requires vendor (BrandRef).
{ "pattern": "dataset_query", "vendor": { "domain": "snowflake.com" } }
{ "pattern": "dataset_query", "vendor": { "domain": "databricks.com" } }
clean_room — privacy-preserving match. Neither party sees the other's raw rows. Requires vendor (BrandRef). The vendor identifies the clean room product (AMC = amazon.com, Snowflake DCR = snowflake.com, LiveRamp clean room = liveramp.com, etc.).
{ "pattern": "clean_room", "vendor": { "domain": "amazon.com" } }
{ "pattern": "clean_room", "vendor": { "domain": "snowflake.com" } }
{ "pattern": "clean_room", "vendor": { "domain": "liveramp.com" } }
{ "pattern": "clean_room", "vendor": { "domain": "habu.com" } }
Why vendor identity is a BrandRef domain (not an enum)
The schema already uses BrandRef ({ domain, brand_id? }) for vendor identity in measurement reporting ((vendor.domain, vendor.brand_id, metric_id)). Reusing it here:
- New entrants (Alibaba Cloud, OpenAI, Databricks Delta Share, vendor-X clean room) declare a domain and they're in. No spec PR, no enum bottleneck.
- TMP unifies cleanly: a buyer agent's
agent_url is the natural identity for tmp_identity_match integrations.
- Verifiable: a vendor's
brand.json can attest to its activation role; buyers can confirm declarations.
cloud_provider is a separate slot from vendor because cloud providers (AWS, GCP, Azure) are infrastructure platforms, not products. AMC is vendor: amazon.com because it's a specific Amazon product; raw S3 push is cloud_provider: amazon.com because it's the cloud's storage primitive. The pattern field disambiguates ("Amazon" means different things in clean_room vs cloud_bucket context).
Per-product and per-seller declarations
Per product (core/product.json):
"audience_activation": {
"methods": [ /* array of activation method entries */ ],
"preferred_method": { /* optional, single entry */ },
"notes": "free-text caveats"
}
Required when the product accepts buyer audiences; absent otherwise.
Per seller (get-adcp-capabilities-response.json → audience_targeting):
"supported_activation_methods": [ /* union of per-product methods */ ]
Source of truth is per-product. The seller-wide field is a union for fast-fail discovery: a buyer can read this once and skip the catalog walk if there's no overlap with their pipeline.
Filter integration
Add audience_activation_method to core/product-filters.json so get_products can narrow results to activatable inventory using existing filter infrastructure. No new filter mechanism — just a new key. Sellers exclude products whose audience_activation.methods doesn't intersect the filter; buyers detect via filter_diagnostics.excluded_by.
Validation rules
| pattern |
required fields |
forbidden fields |
sync_audiences |
(none) |
all others |
tmp_identity_match |
buyer_agent.agent_url |
vendor, cloud_provider, direction |
cloud_bucket |
direction, cloud_provider |
vendor, buyer_agent |
dataset_query |
vendor |
cloud_provider, buyer_agent, direction |
clean_room |
vendor |
cloud_provider, buyer_agent, direction |
Open questions for WG
- SFTP / non-cloud legacy paths. Not modeled in this proposal. SFTP doesn't fit
cloud_bucket (no cloud provider). Three options: (a) drop entirely, since AdCP sync_audiences is the canonical push and the spec shouldn't bless legacy paths; (b) add a file_transfer pattern with a transport field; (c) document SFTP as out-of-band custom integration with no schema entry. Lean (a).
- Reporting symmetry. The same
pattern + vendor/cloud_provider model maps directly to delivery reporting back to the buyer ("seller pushes reports to buyer's S3" vs "seller publishes via Snowflake share"). Sibling RFC for reporting_method writes itself with the same shape. Should land separately to keep WG agendas tight.
- Per-pricing-option variance. Activation method may vary by pricing tier (Snowflake share carries data-egress fees). v1 keeps at the product level; revisit if real cases show variance.
- Identifier-type intersection. A product might support
dataset_query for emails but sync_audiences for MAIDs. v1 ignores this; extend audience_activation.methods[] entry to optionally carry identifier_types: [] if real cases need it.
- Vendor verification. A seller declaring
vendor: liveramp.com should be confirmable by reading liveramp.com's brand.json. Out of scope for v1 schema, but worth flagging — same trust model as the broader AdCP vendor pattern.
Out of scope
- Activation pricing (lives in
pricing-options).
- Authentication / credential exchange specifics per method.
- Buyer-side spend-uplift preferences ("I'll spend more with sellers supporting X") — separate artifact, lives near buy-terms negotiation.
Related
🤖 Generated with Claude Code
Background
The audience-targeting capability today describes what kinds of identifiers a seller accepts (
supported_identifier_types,supported_uid_types,supports_platform_customer_id) but says nothing about how the data moves. AdCP-native sync, TMP identity match, cloud bucket dropoff, vendor-mediated dataset queries, clean room matches — these are the integration realities that determine whether activation is one config switch or three weeks of engineering work for a buyer.The gap
A buyer with a Snowflake-based audience pipeline and a seller that only takes direct-API audience sync are technically compatible (both speak
sync_audiences) and practically incompatible without rebuilding the buyer's pipeline. Today this is discovered at integration time, or worse, at activation time when a campaign starts and audiences don't sync.Today's nearest fields:
audience_targeting.supported_identifier_types— kinds of IDs (email, phone).audience_targeting.supported_uid_types— UID frameworks (RampID, UID2, MAID).audience_targeting.supports_platform_customer_id— platform-native customer IDs.None answer "where does the data move and how."
Proposed addition
A new
audience_activationblock oncore/product.jsonand asupported_activation_methodssummary on theaudience_targetingcapability. Each activation method declares apatternplus pattern-specific fields. Two patterns are AdCP-canonical and first-class; three cover non-AdCP integration realities.AdCP-canonical patterns (preferred)
sync_audiences— bare. Seller declares "I accept audience pushes via the AdCPsync_audiencestool." Any AdCP-speaking buyer can use it.tmp_identity_match— declares specific buyer agents the seller integrates with for TMP runtime identity match. Seller must list each buyer agent it has configured. The integration isn't generic; the seller has set up TMP calls to specific buyer agents.{ "pattern": "sync_audiences" } { "pattern": "tmp_identity_match", "buyer_agent": { "agent_url": "https://buyer.scope3.com" } } { "pattern": "tmp_identity_match", "buyer_agent": { "agent_url": "https://buyer.interchange.com" } }Non-AdCP patterns (legacy / vendor-specific)
cloud_bucket— raw cloud storage push or pull. Requiresdirectionandcloud_provider(aBrandRef).{ "pattern": "cloud_bucket", "direction": "push_to_seller", "cloud_provider": { "domain": "amazon.com" } } { "pattern": "cloud_bucket", "direction": "pull_from_buyer", "cloud_provider": { "domain": "amazon.com" } } { "pattern": "cloud_bucket", "direction": "push_to_seller", "cloud_provider": { "domain": "cloud.google.com" } }directionispush_to_seller(buyer writes to seller-hosted bucket) orpull_from_buyer(seller reads from buyer-hosted bucket). These have different security/legal posture and aren't interchangeable.dataset_query— vendor-mediated query access (Snowflake Secure Data Sharing, Databricks Delta Sharing, BigQuery authorized views). Seller queries a dataset the buyer makes available through the vendor's sharing mechanism. Requiresvendor(BrandRef).{ "pattern": "dataset_query", "vendor": { "domain": "snowflake.com" } } { "pattern": "dataset_query", "vendor": { "domain": "databricks.com" } }clean_room— privacy-preserving match. Neither party sees the other's raw rows. Requiresvendor(BrandRef). The vendor identifies the clean room product (AMC =amazon.com, Snowflake DCR =snowflake.com, LiveRamp clean room =liveramp.com, etc.).{ "pattern": "clean_room", "vendor": { "domain": "amazon.com" } } { "pattern": "clean_room", "vendor": { "domain": "snowflake.com" } } { "pattern": "clean_room", "vendor": { "domain": "liveramp.com" } } { "pattern": "clean_room", "vendor": { "domain": "habu.com" } }Why vendor identity is a
BrandRefdomain (not an enum)The schema already uses
BrandRef({ domain, brand_id? }) for vendor identity in measurement reporting ((vendor.domain, vendor.brand_id, metric_id)). Reusing it here:agent_urlis the natural identity fortmp_identity_matchintegrations.brand.jsoncan attest to its activation role; buyers can confirm declarations.cloud_provideris a separate slot fromvendorbecause cloud providers (AWS, GCP, Azure) are infrastructure platforms, not products. AMC isvendor: amazon.combecause it's a specific Amazon product; raw S3 push iscloud_provider: amazon.combecause it's the cloud's storage primitive. Thepatternfield disambiguates ("Amazon" means different things inclean_roomvscloud_bucketcontext).Per-product and per-seller declarations
Per product (
core/product.json):Required when the product accepts buyer audiences; absent otherwise.
Per seller (
get-adcp-capabilities-response.json→audience_targeting):Source of truth is per-product. The seller-wide field is a union for fast-fail discovery: a buyer can read this once and skip the catalog walk if there's no overlap with their pipeline.
Filter integration
Add
audience_activation_methodtocore/product-filters.jsonsoget_productscan narrow results to activatable inventory using existing filter infrastructure. No new filter mechanism — just a new key. Sellers exclude products whoseaudience_activation.methodsdoesn't intersect the filter; buyers detect viafilter_diagnostics.excluded_by.Validation rules
sync_audiencestmp_identity_matchbuyer_agent.agent_urlvendor,cloud_provider,directioncloud_bucketdirection,cloud_providervendor,buyer_agentdataset_queryvendorcloud_provider,buyer_agent,directionclean_roomvendorcloud_provider,buyer_agent,directionOpen questions for WG
cloud_bucket(no cloud provider). Three options: (a) drop entirely, since AdCPsync_audiencesis the canonical push and the spec shouldn't bless legacy paths; (b) add afile_transferpattern with atransportfield; (c) document SFTP as out-of-band custom integration with no schema entry. Lean (a).pattern+vendor/cloud_providermodel maps directly to delivery reporting back to the buyer ("seller pushes reports to buyer's S3" vs "seller publishes via Snowflake share"). Sibling RFC forreporting_methodwrites itself with the same shape. Should land separately to keep WG agendas tight.dataset_queryfor emails butsync_audiencesfor MAIDs. v1 ignores this; extendaudience_activation.methods[]entry to optionally carryidentifier_types: []if real cases need it.vendor: liveramp.comshould be confirmable by reading liveramp.com'sbrand.json. Out of scope for v1 schema, but worth flagging — same trust model as the broader AdCP vendor pattern.Out of scope
pricing-options).Related
🤖 Generated with Claude Code