Repository navigation
Description
Problem
A buyer that syncs one CRM list to several platforms needs to know, per platform, how many people the list reached and whether it is worth buying against. Ad-tech tools that sync audiences to platforms show exactly this per destination: audience size, match rate, and records sent. AdCP's sync_audiences result cannot carry what the platforms actually report:
- Size is one number.
matched_counthas no bounds and no precision. Most platforms report a range or an approximation for privacy reasons, so a seller has to invent a point value.- Meta returns
approximate_count_lower_bound/approximate_count_upper_bound, and no matched count or match rate (Custom Audience reference). - Google Customer Match returns
size_for_display/size_for_search, bucketedsize_range_for_display/size_range_for_search, andmatch_rate_percentage(user_list.proto). - LinkedIn returns
audienceSizeand a rolling-7-daymatchedCount, both approximate "for member privacy" (segment destinations). - Snap returns
approximate_number_users(customer lists); X returnsaudience_size, null while processing or below minimum (audiences); Pinterest returnssize(API description).
- Meta returns
- Matched is not targetable. Google (search vs display) and LinkedIn (
audienceSizevsmatchedCount) distinguish people matched from people the platform can serve now. AdCP has one field. - Match rate has no basis. Google reports a rate; for LinkedIn it can only be derived from approximate counts; Meta exposes none.
effective_match_ratecannot say which. - No overlap. Buyers deciding whether to run two audiences together, or to suppress one from another, need their overlap. TikTok exposes it through the API (
/open_api/v1.3/audience/insight/overlap/), Amazon DSP exposes overlapping audiences, and Meta exposes it in Ads Manager only. AdCP has no way to ask.
Proposed direction
Two additive changes. Nothing existing changes meaning.
1. Size and match fields on each sync_audiences audience result
{
"audience_id": "crm_customers",
"status": "ready",
"matched_count": 15300000, // unchanged; MAY be absent when the seller cannot report it
"audience_size": { // new: people matched on the platform
"lower_bound": 14000000,
"upper_bound": 16500000,
"precision": "approximate", // exact | approximate | bucketed
"as_of": "2026-10-08T12:00:00Z"
},
"targetable_size": { // new: people the platform can serve now
"lower_bound": 9000000,
"upper_bound": 11000000,
"precision": "bucketed",
"as_of": "2026-10-08T12:00:00Z"
},
"effective_match_rate": 0.42,
"match_rate_basis": "platform_reported" // new: platform_reported | derived
}lower_boundequalsupper_boundwhenprecisionisexact.- A seller that reports size but not match (Meta) omits
matched_countandeffective_match_rate; buyers must not read absence as zero. - Values below the seller's minimum size follow the existing
too_smallstatus and are not disclosed.
2. Overlap as an optional, capability-advertised read
A seller that can compute overlap advertises it in get_adcp_capabilities and accepts:
// request
{ "account": { ... }, "audience_id": "crm_customers", "compare_to": ["site_visitors_30d", "lapsed_buyers"] }
// response
{
"audience_id": "crm_customers",
"comparisons": [
{
"audience_id": "site_visitors_30d",
"overlap": { "lower_bound": 2100000, "upper_bound": 2400000, "precision": "approximate", "as_of": "..." },
"share_of_primary": 0.15, // overlap / size of audience_id
"share_of_comparison": 0.31 // overlap / size of the compared audience
}
]
}- Both shares are returned because overlap is asymmetric; Meta's UI flips the percentage depending on which audience is selected.
- Only aggregate counts. Never member identifiers.
- A seller may refuse comparisons involving an audience below its minimum, with the existing
too_smallsemantics.
Alignment with #7763
#7763 proposes per-account execution readiness: for each product, which account resources it needs, which candidates the account has, and which one the buy uses. An audience is one of those resources. A buyer choosing between a platform's existing custom audiences, or deciding whether a synced list is worth a product, needs the same size facts there as in sync_audiences.
- Add
audienceto RFC: per-account execution readiness for products (required resources, candidates, and binding) #7763's resource kinds, lined up withsync_audiencesidentifiers the wayevent_sourcelines up withsync_event_sources. - An
audiencecandidate inexecution_readiness.resources[].candidates[]MAY carry theaudience_sizeandtargetable_sizeobjects defined here, so one shape serves both surfaces. - An audience below the seller's minimum reads as
setup_requiredthere andtoo_smallhere.
Design questions
- Task name and placement: a standalone read (for example
get_audience_overlap), or a mode on the audience snapshot read proposed in RFC: audience lifecycle snapshots and status-change notifications #5966? - Should
targetable_sizeallow a per-surface breakdown (Google search vs display), or stay one value with the surface left to the seller? - Maximum
compare_tolength. Meta's UI compares up to 5 audiences. - Should overlap also be computable by a buyer-side orchestrator that holds the hashed lists itself, and if so does it belong in this task or in a separate buyer-agent capability?
Related
- RFC: audience lifecycle snapshots and status-change notifications #5966: audience lifecycle notifications. Its open question "which size fields are safe to push" should reference the
audience_sizeobject defined here, not a separate shape. - RFC: per-account execution readiness for products (required resources, candidates, and binding) #7763: per-account execution readiness. Audiences are an account resource a product can need.
- RFC: external audience sources — pass-through references on sync_audiences #6540: external audience sources and their count semantics.
- feat: add sync_audiences task for CRM-based audience management #1125: added
sync_audiences.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
Activity
bokelley commentedon Oct 8, 2026
Triage
Classification: Feature request (RFC — normative additive)
Bucket(s): spec / protocol, media-buy
Status: ready-for-human
Milestone: 3.3.0
One-line ruling: Part 1 (
audience_size/targetable_sizeonsync_audiences) is non-breaking and ready for WG vote after theas_ofcoherency rule is settled; Part 2 (overlap task) needs two design calls before approval.Class: normative — optional fields on existing array item; new optional capability-advertised task.
What the experts said:
matched_countwas already optional insync-audiences-response.json). One blocker:audience_size.as_ofandtargetable_size.as_ofcan diverge from the existinglast_synced_atanchor, breaking the schema's single-clock invariant on count fields. Recommends standaloneget_audience_overlapfollowing existing capability-advertisement patterns; buyer-side hash computation is a different trust boundary and should be explicitly deferred.matched_countas an integer is a protocol fiction on every major platform today;targetable_size(matched vs. serveable) is real and not currently representable. Overlap task has genuine pre-buy demand (suppression lists, add-to vs. create-new decisions). Coupling to RFC: per-account execution readiness for products (required resources, candidates, and binding) #7763 should be loose; both issues are independently useful.as_ofandlast_synced_at; (2)precisionenum semantics (platform quantization metadata vs. protocol representation accuracy — needs a third value for open-ceiling top buckets: Meta reports "10M+", Google has the same case); (3)matched_countsemantic precedence vs.audience_sizewhen both are present. Part 2 defer until Q1 (standalone task vs. RFC: audience lifecycle snapshots and status-change notifications #5966 mode) and Q2 (per-surfacetargetable_size) are resolved — both are one-way wire-shape decisions.My take: The schema already supports these additions cleanly; the only genuine blocker is resolving the
as_ofcoherency rule before Part 1 ships. Part 2 is straightforward to approve once the WG picks Option A or B on task placement — consensus across all three experts favors standalone.Dissent: none.
WG decision 1 —
as_ofcoherency (blocker on Part 1)The existing
sync-audiences-response.jsonif/then requireslast_synced_atwhenstatusisreadyortoo_small. Adding sub-objectas_oftimestamps that can diverge from it creates up to three freshness anchors on one audience item.Option A —
as_ofMUST equallast_synced_at(recommended; no divergence risk):Consumers can safely cross-divide
targetable_size / audience_size. Sellers with delayed reach modeling round up to the sync timestamp.Option B —
as_ofMAY differ (e.g., reach modeled on a T-1 data pipeline):Accurate for platforms that model reach asynchronously, but requires normative prose declaring cross-subobject arithmetic undefined and specifying which timestamp buyers surface to users.
WG decision 2 —
targetable_sizegranularity (one-way door)Google exposes search vs. display targetable counts separately; Meta does not.
Option A — flat single value (current proposal; simpler):
Google sellers choose which surface to report. If per-surface breakdown is needed later, it ships as a new optional
targetable_sizesarray alongside this field — no migration needed.Option B — per-surface array now (forward-looking; design it once):
Expanding flat → array in a later release leaves both fields coexisting with undefined priority semantics. If any current WG member needs per-surface data for budget pacing today, design the array now.
WG decision 3 — Overlap task placement (expert consensus: standalone)
All three experts recommend a standalone
get_audience_overlaptask over a mode on #5966. A mode would couple overlap availability to #5966's 3.4.0 timeline; #5966 slipping would take overlap with it.Proposed capability advertisement shape (following existing
audience_targeting/audience_activationpatterns):Buyer-side hash computation (RFC design question #4) should be explicitly deferred as a separate future capability — it involves a different trust boundary and security profile.
Related: #5966 open question "which size fields are safe to push" should reference the
audience_sizeobject defined here. #7763audienceresource kind can reuse these same size objects without tight coupling — the RFC's cross-reference section already describes the right loose alignment.Triaged by Claude Code. Session: https://claude.ai/code/session_012FdAGq9Duv9zGsw6cAuieY
Generated by Claude Code
feat(schema): report audience size as a range on sync_audiences (#8024)
bokelley commentedon Oct 8, 2026
WG decision brief (3.3) — part 2: audience overlap
Problem. A buyer choosing between audiences (suppress one from another, add to an existing list or create a new one, run two lists together) needs their overlap, and AdCP has no way to ask. It is also the riskiest audience read: repeated queries over changing lists can be differenced to recover a small cell, so the shape matters more than the field names.
Who's pulling (platform evidence from this RFC; not independently re-verified): TikTok exposes overlap through its API (
/open_api/v1.3/audience/insight/overlap/), Amazon DSP exposes overlapping audiences, Meta exposes it in Ads Manager only. Tools that sync audiences to platforms show size and match per destination. No AdCP seller implements this yet.Proposed shape. Draft PR: #8031 (against
main, now that #8024 has merged; experimental,media_buy.audience_overlap). A standalone, capability-advertised read, comparing only audiences the buyer synced on the same account:overlapreusescore/audience-size.jsonand is neverexact. Where it departs from the RFC example: noshare_of_*fields (a point share times a list size the buyer knows recovers the exact count; buyers derive interval shares), andsuppressednever reports zero or says why. Sellers MUST NOT disclose belowminimum_overlap_size, MUST pick the range from the true overlap plus a seller-keyed deterministic offset at least that wide, MUST give a stable answer per pair of memberships, and MUST charge every comparison to a principal-scoped budget before evaluating suppression. Security, protocol and product review changes are folded into the PR.Open questions
compare_to.get_audience_overlap: the triage experts agreed, and a mode ties overlap to RFC: audience lifecycle snapshots and status-change notifications #5966's 3.4 timeline.Out of scope for this cut: seller-owned or third-party segments; buyer-side overlap from raw hashed lists (RFC question 4, a different trust boundary); share percentages; per-surface
targetable_size; audiences from an externalsource; comparison across accounts; #7763 and #5966 integration; a reference seller and compliance storyboard (needed before it can graduate from experimental).3.3 call. Ship in 3.3 as experimental: optional and capability-gated, so no cost to non-implementers. If Q1 and Q2 are not settled in the freeze week, move it to 3.4 rather than ship a privacy rule nobody can pass.
feat(schema): add experimental get_audience_overlap read
bokelley commentedon Oct 31, 2026
Part 1 shipped: audience size as a range on
sync_audiencesin #8024 (3.3.0-beta.0).Part 2,
get_audience_overlap(#8031), is an open draft, was never merged, and has no decision. The brief (#8023 (comment)) said to move it to 3.4 if the two privacy questions were not settled, and they weren't. Per the WG rule ('anything not decided moves to 3.4') only Part 2 moves to 3.4. Objections by Fri 2026-11-06. The milestone stays 3.3.0 for now; it will be moved after Nov 6.