Skip to content

§ 5.3, § 5.5 — Audience: composition, disclosure, and one map of exclusions (#91, #97) - #151

Open
KonstantinMirin wants to merge 293 commits into
IABTechLab:mainfrom
KonstantinMirin:op30-audience
Open

KonstantinMirin wants to merge 293 commits into
IABTechLab:mainfrom
KonstantinMirin:op30-audience

Conversation

@KonstantinMirin

@KonstantinMirin KonstantinMirin commented Nov 4, 2026 •

Copy link
Copy Markdown

What this changes

Draft 1 doesn't say whether two selected audiences combine as AND or OR, or what an audience option discloses. Its block lists are an untyped object. This PR gives § 5.3 and § 5.5 key tables.

  • § 5.3: combine is a Selectable of any and all. The seller's included[] names the operator in effect, and the buyer's selected[] changes it.
  • § 5.3: a buyer can exclude options the seller marks excludable, in excluded[], and their deltas count. Four numbered conditions state whom the line item targets.
  • § 5.3: each AudienceOption states its taxonomy, its Data Transparency Standard 1.1 data_label, and its sensitive_categories[].
  • § 5.3: addressable_scale is an AddressableScale, with a unit and a window.
  • § 5.3: BuyerSupplied and BuyerList have key tables. expected_match_rate is a Fraction, and changes without a new version (§ 4.1.3).
  • § 5.5: accepted_exclusions maps each exclusion type to its enforcement and max_entries. exclusions is one map keyed by type. A long list is a DocumentRef (§ 2.2). An exclusion added after agreed is a delivery.
  • § 5.5: the disclosure rule moves here from § 5.8. It admits the systems and vendors that enforce or verify the lists.
  • § 6.3: the CTV example accepts keywords only as best_effort.

Related issue

Closes #91. Closes #97. Both are Postindustria (IAB Tech Lab member) change requests.

Refs #39, #25, and #71.

Builds on

This PR builds on our property option PR, which builds on our DOOH PR. It builds on our settlement PR, pricing PR, handoff PR, post-agreement PR, and holds PR. These build on our signing PR, buyer writes PR, lifecycle PR, parties PR, errors and extensions PR, and shared types PR. Through them it carries #17, #18, #70, #71, and #72 by @Sirajmx, #73, #74, #75, and #76 by @Kishore-2572, and #117 and #118 by @aleksUIX. Review the commit "Define audience composition and one map of exclusions".

Type

  • Editorial — no normative effect
  • Normative — changes what the spec requires
  • Breaking — would break an implementation already built to this draft
  • Examples / schema / docs only

Checklist

  • The body section is updated — § 2.4, § 2.6, § 2.7, § 3, § 3.4, § 4.1.1, § 4.1.3, § 5.3, § 5.5, § 5.6, § 5.6.1, § 5.8, and § 6.3
  • Appendix A (field index) matches the body — the audiences, addressable_scale, accepted_exclusions, and exclusions rows take the new types. scripts/check_appendix.py passes
  • Appendix B (fields by marker, and the counts) matches the body — exclusions_accepted becomes accepted_exclusions; no count changes
  • Any affected example in examples/ is updated and still parses. The display example writes combine, data_label, expected_match_rate, seller_side, and the accepted_exclusions map. The issued example writes the map, with keywords by reference, and recomputes record_digest. The CTV example gains accepted_exclusions. scripts/check_examples.py checks combine, excluded[], and Map keys, and passes. scripts/check_pricing_fixtures.py passes 60 of 60
  • RFC 2119 keywords used deliberately — MUST / SHOULD / MAY are not synonyms
  • The no-inheritance rule (§ 2) still holds — every key sits on the line item
  • Anything selectable declares available[] and included[]; anything settable declares bounds (§ 3.1, § 3.2) — combine declares both; no new settable fields
  • No confidential or commercially sensitive content

Knock-on effects

Open questions

  1. [Change] § 5.3 — Say whether selected audiences combine as AND or OR, and how buyer segments and exclusions combine with them #91's questions 2, 3, and 5 carry over; question 4 is answered there. Question 1 is settled: combine is REQUIRED when more than one seller audience can be in effect, and included[] holds the seller's default.
  2. max_entries has no stated consequence. Should a seller reject a list over the limit, as our comment on #71 suggests?
  3. What does pre_serve promise? [Change] § 5.5 — Buyer-supplied block lists (exclusions_accepted, exclusions) #25 defers guaranteed enforcement to 4.0, and this PR doesn't define it.
  4. [Change] § 5.2, § 5.3 — Disclose audience taxonomy, data label, sensitive categories, and child-directed properties #97's questions 2, 3, and 5 carry over. Question 4 is settled: sensitive_categories[] is an open vocabulary with ten core terms.

Contribution Terms

Analyzed and generated with the help of Claude, fully reviewed by me.

Separate shared and issued proposals, and add issued_from. Define the
binding record, record_digest, and assent[] entries, freeze a version's
offered terms, and state one staleness rule for asks and holds.

Give each act one history action, name the status types, make the
line-item transitions exhaustive, define a firm entry per pricing entry,
and list the allowed decline grounds once. State agreed once.

Remove buyer state from the shared examples, add an issued, partly
agreed example, and recompute its record_digest in the checker.
Keep record_digest only on assent entries, and state the exact digest
bytes. Cut the record to terms: min_rate, the advisory fields, segments,
and the suppression list leave it, and seller_rate and deal_id_issuance
go. Give AssentEntry a key table with four roles, so only assent[]
decides agreed, and move idempotency_key onto the entry.

Name the Commit and its CommitResult. The seller recomputes the digest
over the line items as they stand, and rejects in a stated order. A
commitment entry stops being live when its commit goes stale or void.

Carry entries in messages signed under the OpenProposal profile of Web
Bot Auth, as optional evidence. Add HttpsUrl, and replace terms_ref with
terms_refs[] of DocumentRef. Add the agreed record example, and teach
the checker the assent rules.
Add selected[] as the complete set of options in effect and value as the
one buyer key on a settable field, with an explicit default. An envelope's
value narrows allowed[], and the bare-value fallbacks go. Every object
option has an id, unique in its field. Name BuyerWrites, LineItemWrites,
and the availability read.

Give agreed_rate one formula, on the committed entry only, rounded once.
Rename gross_rate to list_rate, floor to min_rate, a hint, and delta_pct
to delta_fraction, a fraction. Make list_rate and commitment_bounds
requestable, mark commitment mixed, and give transaction_mechanism
max_select 1.

Split geo into a settable geo and a selectable markets over GeoCode, type
device as AdCOM codes and daypart as ClockWindow, and delete
supported_formats. Update the examples, the issued record_digest, the
appendices, and the example checker.
Split what a request or response carries from the message envelope in
section 1.2, and resolve its placeholders. The wire contract governs only
once it is on a standards track. Name the baseline as the VersionRef of
the agreed line item at the version of its agreed record.

Add change_requests[] in section 4.4 with the OpenDirect 2.1
ChangeRequest fields except webhook, plus baseline, actor, at, and
cancellation. Require orderid only when the line item has an order
reference. Remove correlation_id, give ExternalReference a key table,
rename role to reference_type, and replace io with order and line.

Let an entry carry ext outside the record, and ask in section 8 how an
entry states a change other than a cancellation. CancellationNotice stays
pending until its key table lands. Retitle sections 5.10 and 6.8, and
update the agreed example, the appendices, the issue templates, and the
checkers.

Refs IABTechLab#59, IABTechLab#68
Put one table of transaction_mechanism values in section 5.9. It states
which are deal mechanisms and which delivery_type each allows. Key
section 1.1 on those values, with each one's reference type and change
path. An option is { id, delivery_type }, and sov_basis and sov_share
describe a share of voice. Remove open_auction, because with no deal ID
no bid request can name a line item.

Map a line item agreed under a deal mechanism to a Deals API 1.0 Deal
that deal_origin pushes, with price_type saying how agreed_rate clears.
Map a direct_io line item, and a programmatic guaranteed reservation, to
an OpenDirect 2.1 Order and Line, and state what the record doesn't hold.

Define each creative_delivery.method as a creative path. Remove
buying_route and supported_order_systems, and type serving_platform as a
Domain. Update the examples, digests, manifest, appendices, and checkers.

Refs IABTechLab#132, IABTechLab#133, IABTechLab#93, IABTechLab#109
Replace hold_status with hold_terms, a seller-set offer inside the binding
record, and hold, live state outside it, so the removal path has no
exception. Rename state and hold_expires_at to status and valid_until, add
position, the order in which holds are granted, and leave hold absent until
the buyer first asks.

Close the hold machine: add declined, re-entry to requested, and the
re-offer as listed transitions, and state the cap on valid_until. Give hold
a version and two optional keys, requested_terms as LineItemWrites and
held_availability as Availability, which stays pending until its key table
lands. Remove hold_scope: under linked_execution all, holds move as a unit.

Stop the CTV example offering a hold on private_auction, show a full hold in
the issued example, and recompute its digest. Drop the checker's handling of
exceptions in removal paths, and check the keys of LineItemWrites.

Refs IABTechLab#66
Open the cost_method vocabulary, with a unit and a rate per for each
core term in section 5.6.5. Make pricing entries alternatives named by
pricing_id. Read every Amount in the committed entry's CurrencyCode,
remove commitment.currency, and ask in section 8 what basis a money
value is on.

Replace min_spend and the budget keys with commitment_bounds.spend, and
the impression keys with pricing[].unit_bounds. Give Availability,
CommitmentBounds, and MinCommitment key tables, and point the section
1.1 totals at the seller total. Define cancellation options, the notice
a change request records, and exclusivity options.

Teach the example checker the commitment arithmetic, the bounds, and the
cancellation checks. Have it check that an array whose row says MUST be
non-empty holds an entry. Align the pricing vectors with these names,
and update the examples, digests, manifest, and appendices. Replace the
PG and PMP floor example in CONTRIBUTING.md and the comment template,
since pricing entries can name their mechanisms.

Refs IABTechLab#94, IABTechLab#98, IABTechLab#117, IABTechLab#127, IABTechLab#115, IABTechLab#30, IABTechLab#70, IABTechLab#125, IABTechLab#121
Settlement reads the terms in force: the agreed record plus any change
the applying system has applied. Section 5.7.1 names what no downstream
standard states, and states the shortfall and remedy rules once.

controlling_measurement names whose count is invoiced and when it is
final. measured_by and counted_by are a Measurer, with a qualifier for a
product or method. CommittedMetric gets a key table with level and
direction, and basis and seller_reported go. metric gets a core table of
rate terms that cite their standards. shortfall_remedy becomes a
ShortfallRemedy with RemedyTerms, and section 8 gains question 10.
verification[] holds domains, viewability_standard gains mrc, feed_type
and delivery_mechanism become report_type and delivery_method, and
guaranteed covers a FLAT entry.

The examples name the measurement vendors by domain, and the checkers
read the metric table and type the new keys.
When channel is dooh, a property is a set of screens of one venue type,
with venue_type, allocation, min_screens, screens[], slots_per_loop, and
sync_groups[]. frequency_cap.per gains the screen term, and a loop_time
share derives from the loop.

Section 5.6.4 defines a play and an impression. delivery_counting,
REQUIRED on a dooh line item, holds the play tolerance, a keyed
proof_of_performance, partial_play_credit, and a nested
impression_multiplier that only a line item counting impressions needs.
The committed quantity is in the committed entry's unit, and the
multiplier's source controls the count of impressions.

Add the DOOH example. The example checker reads the new paths and checks
the counter against the multiplier's source.
# Conflicts:
#	spec/openproposal-3.0.md
PropertyOption has one key table in section 5.2.4, and a screen has its
own in section 5.2.8, with Loop and SyncGroup. App identity, seller
relationship, child-directed status, and DOOH screens each get a
numbered section.

Each property states the seller's relationship and the accounts a buyer
checks, and declares whether it is directed to children. AppId is
{ store, bundle }, and App adds store_url and developer_domain. The
platform key becomes store, an open vocabulary of store names. A block
list's app_bundle[] becomes apps[] of AppId.

A key table follows a lead-in that names its type, and an object
option's type ends Option. The table lint enforces both, and the example
checker reads the property, screen, and app tables.

Closes IABTechLab#88
Refs IABTechLab#15, IABTechLab#17, IABTechLab#96, IABTechLab#97, IABTechLab#71
AudienceOption, AudienceSelectable, BuyerSupplied, BuyerList, and
AddressableScale get key tables. combine is a Selectable of any and all,
so included[] names the operator in effect, and a buyer names the options
it excludes in excluded[]. An audience option states its taxonomy, data
label, and sensitive categories, and no longer carries addressable_scale.
match_rate_expected becomes expected_match_rate, a Fraction.
expected_match_rate changes without a new version.

accepted_exclusions maps each exclusion type to its enforcement and
max_entries. exclusions is one map keyed by type, and each value is an
array of entries or a DocumentRef, which replaces list_ref.
activation_route names seller_side, a categories entry is a
TaxonomyCodes, and a domains or categories entry covers only itself. The
disclosure rule moves to section 5.5 and admits the systems and vendors
that enforce or verify the lists. The CTV example accepts keywords only
as best_effort.

The checkers read the new tables, Map keys, and removal paths below a
typed field.

Closes IABTechLab#91
Closes IABTechLab#97
Refs IABTechLab#39, IABTechLab#25, IABTechLab#71
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant