Repository navigation
Description
What kind of change?
Change a field's type or shape
Which section?
5.7 — Guarantees
Current text
| `committed_metrics[]` | Array[Object] | requestable | `{ metric, value, basis }` tuples — `viewable_rate` for display, `completion_rate` for video/audio/CTV, an audience-modelled metric for DOOH. Seller declares a ceiling; a buyer MAY request above it |
| `measurement_source` | Object | selectable | `available[]` of `{ vendor, attribution_window, qualifier }` with `pricing`. Lets a buyer transact in its own currency |
| `shortfall_remedy` | Object | selectable | `available[]` from `makegood` \| `credit` \| `none`, plus `remedy_terms` |Proposed text
§ 5.7, `committed_metrics[]`: each tuple is `{ metric, level, direction }`.
`level` replaces `value`, and `direction` is REQUIRED: `at_least` |
`at_most`. Core `metric` terms: `viewable_rate`, `completion_rate`,
`ivt_rate`, `impressions`. Each term's definition names its standard, so
`basis` goes. Replace "Seller declares a ceiling; a buyer MAY request above it"
with "Seller declares its offered `level`. A buyer MAY request a stricter
`level`, one further in `direction`. A request MUST NOT change a tuple's
`direction`."
§ 5.7, `measurement_source`: options are `{ id, measured_by,
attribution_window, qualifier }`, with `measured_by` replacing `vendor`.
Add after the `measurement_source` row:
| `controlling_measurement` | Object | selectable | Whose count of billable units is invoiced. `available[]` of `{ id, counted_by, qualifier, discrepancy_threshold, final_after }`, `max_select: 1`. `included[]` MUST name exactly one option. REQUIRED on a line item with `committed_metrics[]`, `commitment_bounds.spend`, or a `pricing[].unit_bounds`. See Settlement below |
#### Settlement
`measurement_source` measures committed values; its `attribution_window` isn't
a settlement window. `controlling_measurement` counts the units the invoice
uses. Counted delivery, including delivery that still counts after
`commitment.flight.end`, falls in an invoice period. The seller sets the
period in `billing.invoice_period` (§ 5.10), a core term or an extension
term `<domain>:<term>`. The core terms are `month`, a calendar month and the
default, and `cycle`, whose `billing.cycle_length` is an ISO 8601 duration
such as `P28D` (4 weeks).
- `counted_by`, like `measured_by`: `seller`, `buyer`, or a vendor's
registrable domain. `qualifier` names a product, such as an ad server. When
`channel` is `dooh` and the line item counts impressions, `counted_by` MUST
be the source of the line item's `delivery_counting.impression_multiplier`. When
the `pricing[]` entry the buyer commits under has `cost_method` `CPP`,
`counted_by` MUST be its `cost_parameters.rating_source`.
- `discrepancy_threshold`: a fraction of the controlling count. A larger gap
over an invoice period, with the controlling count lower, opens
reconciliation.
- `final_after`: an ISO 8601 duration, such as `P30D` (30 days). A count is
final that long after its invoice period ends. Committed values, whichever
source measures them, are final that long after `commitment.flight.end`.
A shortfall is a final value that misses a committed `level` in its
`direction`, under any `delivery_type`. A committed `level` is guaranteed in
its own right. Final delivery below `commitment.amount` is a shortfall only
where the applicable `delivery_type` is `guaranteed`. Delivery is counted in
units when `commitment.basis` is `units`. When it is `spend`, delivery is
valued against `commitment.amount` without `delta_flat` charges. A unit is
worth `agreed_rate` ÷ rate per, and a `FLAT` flight day its share of
`agreed_rate`. Every shortfall follows the `shortfall_remedy` rules below.
`shortfall_remedy`: the options in effect, `selected[]` or else `included[]`,
are ordered, first choice first. `none` MUST be the only option in effect. It
means no remedy for any shortfall, and committed levels become targets, which
an agent MUST NOT present as guaranteed. At a shortfall, the seller offers the
first remedy. The buyer MAY refuse a `makegood`, and the seller then offers the
next. If none remains, the shortfall settles under `remedy_terms`. A makegood
MUST NOT run past `commitment.flight.end` without the buyer's consent. A
seller MAY offer that consent upfront in `remedy_terms`: `makegood_window`, an
ISO 8601 duration past the flight end, and `makegood_type`, a core term
(`same_unit`, `comparable_unit`, `added_time`) or an extension term. A buyer
that commits with `makegood` in effect consents to a makegood within
`makegood_window`.
Under `sov_basis: impressions` (#93), the promised share is the offered
`sov_share`. The delivered share is measured against the same denominator
and pool, so the two are comparable.
Reports, restated counts, reconciliation, and the remedy workflow run
downstream.Why
A § 5.7 guarantee can't be settled from the agreed record. measurement_source lets a buyer pick a measurement provider to "transact in its own currency". Nothing says which way a committed value binds, whose count is invoiced at what tolerance, when a count is final, or what follows a refused makegood.
- For an IVT rate, lower is stricter, so "request above it" runs the wrong way.
- § 6.2 offers IAS or DoubleVerify on a CPM line. Neither is the ad server whose impressions are billed. The IAB/4A's Standard Terms and Conditions 3.0 name a Controlling Measurement and a 10% discrepancy threshold (§ XIII). OpenDirect 2.1's Order and Line objects have neither.
- T&Cs § VI(b): a makegood applies below "guaranteed levels, as set forth on the IO". With none agreed, the agency may take a credit; past the IO, a makegood needs its consent. § VI(c) rules makegoods out for CPA, CPL and CPC.
- OOH is commonly billed by the 4-week posting cycle, and a makegood past the flight is normal there, as @premesh notes. The seller states both upfront. #125 covers the cycle as the unit bought.
- A committed metric is a guaranteed level under any delivery type; delivery is one only when guaranteed, which no key states; our
delivery_typechange request adds one.
As drafted (§ 5.7):
stateDiagram-v2
state "agreed, remedy selected at composition" as agreed
agreed --> shortfall : ? whose count, what tolerance, final when
shortfall --> makegood : makegood selected
shortfall --> credit : credit selected
shortfall --> [*] : none selected
note right of shortfall
? which way a value binds
? buyer refuses the makegood
end note
Proposed:
stateDiagram-v2
state "downstream, against the agreed record" as downstream {
state "final value misses level in direction" as shortfall
state "remedy offered" as offered
state "settled under remedy_terms" as fallback
[*] --> shortfall
shortfall --> offered : first remedy in effect
offered --> applied : buyer accepts, or credit
offered --> offered : buyer refuses makegood, next remedy
offered --> fallback : buyer refuses, none left
}
agreed --> downstream : controlling count, final_after
note right of agreed
none: no remedy, levels are targets
end note
#38 names the source that settles each committed value and leaves windows to 4.0. This adds direction, the invoiced count, finality, and the remedy order. #20 can defer the procedure, not the terms, to 4.0. Details: Settlement terms: full rationale and examples.
Knock-on effects
- Appendix A gains a row, and Appendix B counts one more
selectablefield. § 5.10billinggainsinvoice_periodandcycle_length. The § 6 examples gaindirectionandcontrolling_measurement. - #38: its tuple takes the same shape,
measured_byreplaces itsvendor, and its "ceiling" sentence takes the same replacement. Itscounts[]carries the IVT filtration, so this adds no window. For itscounts[]to settleivt_rate, itsnumeratorlist needs an invalid-impression value. - Our DOOH plays and impressions change request and our cost-method filing: the DOOH multiplier source and the CPP
rating_sourceare thecounted_by. - § 5.7,
measurement_source: "Lets a buyer transact in its own currency" means a trade currency, next to ISO 4217pricing[].currency. Replace with "Lets a buyer choose the measurement provider it transacts on". - Our agreed-baseline filing: this defines the remedy term; the downstream standard applies it.
Open questions for the working group
- When a shortfall exhausts the remedies in effect, should it settle under
remedy_terms, as proposed, fall back to a credit as T&Cs § VI(b) on makegoods does, or make a sole makegood that runs within the flight binding on the buyer? - Should committed values become final at the controlling option's
final_afteraftercommitment.flight.end, as proposed, or should eachmeasurement_sourceoption carry its ownfinal_after? - Should § 5.7 Guarantees keep the full remedy rules (offer, refusal, next remedy), or only the remedy order and the flight-end consent rule, leaving the rest to the downstream standard as our agreed-baseline filing does for changes?
- When counts differ by more than
discrepancy_threshold, should the record state the outcome T&Cs § XIII(d) on discrepancies offers (treat the gap as under-delivery, or pay on the controlling count plus the threshold), or leave it downstream, as proposed? - If our
delivery_typechange request isn't adopted, what should decide whether delivery belowcommitment.amountis a shortfall: the selected deal mechanism, a guarantee flag in § 5.7 Guarantees, or nothing in 3.0?
Would this break an implementation already built to this draft?
Yes — breaking
Alternatives you considered and rejected
- Inferring
directionfrommetric: the metric list is open. - Mandatory
credit: TV commonly offers a makegood as the only remedy. - Leaving it to referenced legal terms (#27
terms_refs[]): the T&Cs default turns on ad-server certification an agent can't check (§ XIII(b)), and the third-party ad server is named per IO (§ I(a)).
You are commenting as
Other — IAB Tech Lab member (Postindustria).
Before you submit
- I have read CONTRIBUTING.md and agree my contribution may be published under this repository's licence.
- This contains no confidential or commercially sensitive information.
Revised 2026-11-03: Adds the delivered share, as @premesh answers on #134. Takes the names of the PR that carries this change: level, measured_by, counted_by, and core metric terms in place of basis.
Analyzed and generated with the help of Claude, fully reviewed by me.
Activity
premesh commentedon Oct 27, 2026
Two places where OOH settles differently from what's proposed:
Invoice period. OOH is commonly billed by the 4-week posting cycle, not the calendar month, and a cycle often spans two months. Suggest
invoice_periodas a seller-set field:calendar_month | cycle, withcycle_lengthwhen it'scycle. Calendar month can stay the default.Makegood shape. In OOH, a makegood usually means extra days on the same unit or a comparable unit, and that often lands after the original flight end. That's normal, not an exception the buyer has to approve case by case. I'd keep the consent rule but let the seller offer it upfront:
remedy_terms.makegood_window(how far past flight_end a makegood may run) andmakegood_type: same_unit | comparable_unit | added_time. If the buyer selects that option at commit, consent is given.