Skip to content

[Change] § 5.7 — Make a guarantee settleable: direction, controlling measurement, remedy order #95

Open

Description

@KonstantinMirin

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_type change 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
Loading

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
Loading

#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 selectable field. § 5.10 billing gains invoice_period and cycle_length. The § 6 examples gain direction and controlling_measurement.
  • #38: its tuple takes the same shape, measured_by replaces its vendor, and its "ceiling" sentence takes the same replacement. Its counts[] carries the IVT filtration, so this adds no window. For its counts[] to settle ivt_rate, its numerator list 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_source are the counted_by.
  • § 5.7, measurement_source: "Lets a buyer transact in its own currency" means a trade currency, next to ISO 4217 pricing[].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

  1. 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?
  2. Should committed values become final at the controlling option's final_after after commitment.flight.end, as proposed, or should each measurement_source option carry its own final_after?
  3. 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?
  4. 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?
  5. If our delivery_type change request isn't adopted, what should decide whether delivery below commitment.amount is 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 direction from metric: 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

  1. added
    change-requestProposes specific normative wording
    normativeChanges what the spec requires
    breakingWould break an implementation already built to this draft
    on Oct 23, 2026
  2. premesh commented on Oct 27, 2026

    @premesh

    Two places where OOH settles differently from what's proposed:

    1. 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_period as a seller-set field: calendar_month | cycle, with cycle_length when it's cycle. Calendar month can stay the default.

    2. 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) and makegood_type: same_unit | comparable_unit | added_time. If the buyer selects that option at commit, consent is given.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    breakingWould break an implementation already built to this draftchange-requestProposes specific normative wordingnormativeChanges what the spec requiressection:5.7-guarantees

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions