Repository navigation
§ 5.3, § 5.5 — Audience: composition, disclosure, and one map of exclusions (#91, #97) - #151
Open
KonstantinMirin wants to merge 80 commits into
Open
KonstantinMirin wants to merge 80 commits into
KonstantinMirin wants to merge 80 commits into
Conversation
§ 5.2 properties can carry apps[] (platform, bundle, storeurl, domain), keyed as the OpenRTB 2.6 app object where one exists. Each property must carry domains, apps or both. The CTV example carries an app. Refs IABTechLab#15
§ 5.6 defines floor as the seller's offer floor at proposal time, not the downstream auction floor and not a guarantee that bids will clear. Editorial: the meaning of the field is unchanged. Refs IABTechLab#16
Without apps[].domain a buyer has nothing to run the app-ads.txt check against. RECOMMENDED (SHOULD) rather than a conditional REQUIRED, as the object has no field in which a seller claims app-ads.txt authorisation. Refs IABTechLab#15
A proposal can say its line items must be bought together (linked_execution, § 4.1), and a line item can name the line items or spend that must be in the same commitment (requires, § 5.6.3). A bonus line is a line item with requires and its own price. The § 2 "binding terms" hook now points at a field, and the Summary Representation carries has_requires and linked_execution. Adds a CTV bonus line example (§ 6.5) and linked_execution: none to the proposal example. Refs IABTechLab#23
The seller declares which exclusion types it accepts and how it
enforces each (exclusions_accepted); the buyer supplies its lists
(exclusions). Blocked apps carry their store, { platform, bundle },
so one store id is never applied across stores. Exclusions are
recompute inputs (§ 3.3) and are never disclosed to other parties
(§ 5.8). The display example declares and supplies lists.
Refs IABTechLab#25
A line item whose rate differs by market can declare geo with the selectable structure of § 3.1: available[], included[], pricing deltas and max_select. A geo that declares only allowed[] stays settable, so existing payloads are unchanged. When several priced markets are selected, the highest delta applies. The audio example is priced by market. Refs IABTechLab#14
A commitment names the proposal and version it was priced against (§ 5.6.1). The seller rejects a new attempt on a stale version, or past valid_until or price_valid_until, and returns the current version. An authenticated replay with the same idempotency_key and terms returns the stored result without re-running those checks; the same key with different terms is a conflict. Keys are opaque and scoped to one buyer and seller pair. § 4.1 states that each revision while published increments version. The display, CTV and audio examples carry proposal_id and version. Refs IABTechLab#24
§ 4.1 adds an optional, immutable proposal_template_id linking an issued proposal to the seller's template. Each issued proposal has its own status, version and negotiation_history[], and buyers never need the template id to transact. § 7 adds a non-normative note separating seller-side templates from the issued proposals buyers commit against. Appendix A gains one row; Appendix B counts immutable 6 → 7 and 72 fields. The proposal example carries a proposal_template_id. Refs IABTechLab#26
§ 5.8 adds terms_ref ({ url, sha256, version }), REQUIRED when
terms_acceptance_required is true, hash-pinned and frozen at agreed, so
assent binds to an exact document. § 5.10 adds agreement_ref, an
informative pointer to the master or annual agreement a line item is
priced under, and documents the io and agreement roles on
external_references[]. IO generation is stated to be a connector
concern, and § 7 adds a non-normative note on relationships.
agreement_ref is seller-set; a buyer-held agreement id travels as an
external_references[] entry with role: agreement, so the field keeps
one marker (§ 3).
Appendix A gains two rows; Appendix B counts seller-set 29 → 31 and
73 fields. The display example carries terms_ref.
Refs IABTechLab#27
A new § 2.3 lets a seller publish its public standard line items at /.well-known/openproposal.json: seller_id, generated_at, spec_version and, per proposal, proposal_id, version, the Summary Representation of each line item and a full_url. ETag / Last-Modified are required, only line items with visibility public appear, and entries must match the current version. Buyers discover from the manifest, then fetch the Full Representation of shortlisted line items. Adds examples/manifest.json (§ 6.5) and visibility: public to the CTV and audio examples; the registry_gated display line item is not listed. Refs IABTechLab#29
The specification does not define authentication yet (WS1; see IABTechLab#62), so the replay rule now applies to a replay from the same buyer rather than an authenticated replay. Refs IABTechLab#24
agreement_ref.parties used buyer_id, which the specification does not define. parties[] now names the seller by its seller_id and the buyer by the id it holds in eligible_bidders[] (section 5.8). Refs IABTechLab#27
The rule that a hold on a linked_execution: all proposal uses hold_scope: proposal came from a comment on IABTechLab#23, not the change request as filed. It moves to the PR description as a point for the working group, so this PR carries only the filed change. Refs IABTechLab#23
IABTechLab#25 names the content-category list iab_content_category[], a list of IAB Content Taxonomy ids. The earlier commit renamed it content_category with a version-pinned taxonomy_ref, which nobody proposed. This restores the filed name and shape; which taxonomy version to reference is left to the working group. Refs IABTechLab#25
IABTechLab#14 doesn't say how deltas combine when a buyer selects more than one priced market, and neither did any comment on it. The earlier commit said the highest delta applies; that is a design choice nobody proposed, so it moves to the PR description as a question. Refs IABTechLab#14
Read the media condition from the ad served when an impression accepts several media, name the seller as the party that serves, place linear TV outside the table, and state environments as (distribution channel, device type) pairs. Insert environments.available[] into the summary list without rewrapping it, shorten the changelog entry and drop audio_streaming from OQ-7 in docs/open-questions.md. Refs IABTechLab#90
time_zone is the line item's clock for daypart windows and
frequency_cap.period: an IANA time zone name or viewer_local. A window
is { days[], start, end } in civil time with an exclusive end later
than start, up to 24:00; a window that crosses midnight is two windows.
List the `days[]` values once in the `daypart` row, as `monday` | ... | `sunday`. Write HH:MM, America/New_York, and UTC as plain text, since they're a format and examples, not field names. The meaning is unchanged.
"At least one of" an empty list is never satisfied, so the bonus line would fail a literal check. An absent key sets no condition. Only the examples change; the any_of[] row and the rules stay as filed in IABTechLab#23. Refs IABTechLab#23
The floor row now says it "neither constrains nor describes the downstream auction floor", as IABTechLab#16 asked, and names that floor: the per-impression floor the exchange applies at auction time (OpenRTB 2.6 Imp.bidfloor). Refs IABTechLab#16
- Rename apps[].domain to developer_domain, as IABTechLab#15 filed it. It is the developer domain from the store listing that app-ads.txt uses, not OpenRTB 2.6 app.domain, which is the domain of the app. - Define platform as the store that issued bundle, since a bundle is unique only within its store. - List apps[].platform and apps[].bundle in the Summary Representation (section 2.1), as IABTechLab#15 asked. Refs IABTechLab#15
From the Postindustria review on IABTechLab#73: - a replay matches on the same body, every value the buyer sent except idempotency_key, and returns the stored result whether an acceptance or a rejection; a retry against a new version uses a new key; - version increments on each revision of the proposal, not only while published, so a counter under review also moves it; - "deterministic" now says what the checks depend on: the stored proposal and the time the seller receives the attempt; - the price check names the pricing[] entry the commitment is priced against. Refs IABTechLab#24
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
This was referenced Nov 4, 2026
Make commitment.advertisers[] REQUIRED, so a commitment says whom the spend is for. Make ground REQUIRED on a decline entry. Require an answer to a commit under a firm entry while the entry holds, so that silence can't work as a decline on no ground. Refs IABTechLab#65, IABTechLab#126, IABTechLab#153
State that held means reserved inventory. Keep a hold live while a commit made during it is open, so a seller can't leave the commit unanswered until the hold lapses and then decline it for lack of availability. Add the seller's hold reference and renewal_right, an offered term for the right to the next cycle. Refs IABTechLab#66
Add seller_domain to a VersionRef outside its proposal, because a proposal_id is unique only within a seller's domain. Let a Deals API push carry the baseline in ext.baseline, so a DSP can join the deal to its record. Refs IABTechLab#31, IABTechLab#132
State the sign of agreed_rate and have the checker flag a spend commitment with no rate. Let a counter of list_rate also change included[], for a counter on a composed rate. Add location to separation, and have a demographic term state how it treats co-viewers and unknown age. Correct the discussion document's unit wording. Refs IABTechLab#38, IABTechLab#98, IABTechLab#117
A commitment now names whom the spend is for.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.
combineis aSelectableofanyandall. The seller'sincluded[]names the operator in effect, and the buyer'sselected[]changes it.excludable, inexcluded[], and their deltas count. Four numbered conditions state whom the line item targets.AudienceOptionstates itstaxonomy, its Data Transparency Standard 1.1data_label, and itssensitive_categories[].addressable_scaleis anAddressableScale, with a unit and a window.BuyerSuppliedandBuyerListhave key tables.expected_match_rateis aFraction, and changes without a new version (§ 4.1.3).accepted_exclusionsmaps each exclusion type to itsenforcementandmax_entries.exclusionsis one map keyed by type. A long list is aDocumentRef(§ 2.2). An exclusion added afteragreedis a delivery.keywordsonly asbest_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. Our DOOH PR 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 last non-merge commit.
Type
Checklist
audiences,addressable_scale,accepted_exclusions, andexclusionsrows take the new types.scripts/check_appendix.pypassesexclusions_acceptedbecomesaccepted_exclusions; no count changesexamples/is updated and still parses. The display example writescombine,data_label,expected_match_rate,seller_side, and theaccepted_exclusionsmap. The issued example writes the map, withkeywordsby reference, and recomputesrecord_digest. The CTV example gainsaccepted_exclusions.scripts/check_examples.pycheckscombine,excluded[], andMapkeys, and passes.scripts/check_pricing_fixtures.pypasses 60 of 60selectabledeclaresavailable[]andincluded[]; anythingsettabledeclares bounds (§ 3.1, § 3.2) —combinedeclares both; no newsettablefieldsKnock-on effects
exclusions_accepted,list_ref,taxonomy_ref,match_rate_expected,provenance, an option-level or Integeraddressable_scale, oractivation_routepublisher_sideno longer conforms. An audience option needstaxonomy,data_label, andsensitive_categories[]. ABuyerListneedslist_id.audiencesneedscombinewhen more than one seller audience can be in effect.combine: { allowed[], value }becomes aSelectable. The seller names a default, so the buyer needn't write an operator.taxonomy_refbecomestaxonomy, because_refis reserved forDocumentRefandEntryRef(§ 2.6). Its child-directed rows landed with our property option PR.domain,iab_content_category, andkeywordbecomedomains,categories, andkeywords. Acategoriesentry is aTaxonomyCodes. Adomainsorcategoriesentry covers only itself.addressable_scale.unittakes thefrequency_cap.perterms andperson, as [Comment] § 5.3:addressable_scalehas no unit #39 suggests. [Comment] § 5.3:addressable_scalehas no unit #39'smodeledflag isn't added.DocumentRefanswers itslist_refpoint.appsentries keep theAppIdthat @fgranata and @aleksUIX asked for on [Change] § 5.5 — Buyer-supplied block lists (exclusions_accepted, exclusions) #25.line-item-ctv.yamland § 6.3. Our formats PR reconciles the two.Open questions
combineis REQUIRED when more than one seller audience can be in effect, andincluded[]holds the seller's default.max_entrieshas no stated consequence. Should a seller reject a list over the limit, as our comment on #71 suggests?pre_servepromise? [Change] § 5.5 — Buyer-supplied block lists (exclusions_accepted, exclusions) #25 defers guaranteed enforcement to 4.0, and this PR doesn't define it.sensitive_categories[]is an open vocabulary with ten core terms.By opening this pull request I agree my contribution may be published under this
repository's licence, as set out in CONTRIBUTING.md.
Analyzed and generated with the help of Claude, fully reviewed by me.