Skip to content

Account for seller fees after selecting one price - #117

Draft
aleksUIX wants to merge 3 commits into
IABTechLab:mainfrom
aleksUIX:contribution/pricing-arithmetic
Draft

aleksUIX wants to merge 3 commits into
IABTechLab:mainfrom
aleksUIX:contribution/pricing-arithmetic

Conversation

@aleksUIX

@aleksUIX aleksUIX commented Oct 24, 2026 •

Copy link
Copy Markdown

#94 treats pricing[] as alternatives, while #115 adds seller fees as extra rows and leaves derived_units unchanged. At USD 25 CPM, a USD 50,000 commitment containing a USD 2,500 fee leaves USD 47,500 for media, or 1.9 million impressions.

This adds discussion wording and 60 fixed calculation vectors. amount uses the same terms as agreed_rate, without choosing gross or net commission treatment or settling #115's tax question. Selected flat charges contribute once and cannot be separate pricing alternatives. Spend requires a positive agreed rate; units commitments permit a zero rate. Minimum-spend and budget bounds include flat charges.

The supporting calculator preserves an explicitly accepted counter below a posted floor and returns floor_check: not_checked. Passing arithmetic does not establish seller acceptance, reserve inventory or authorize a commitment. Tax-inclusive arithmetic, print adjustments and general mandatory-fee structures remain outside this profile.

The normative spec and field indexes are unchanged. If the wording is adopted, the affected body, appendix and example updates should land together.

Validation: 60 vectors, existing appendix checks and 11 YAML files pass. Three added zero-rate cases fail against the prior published calculator and pass with this change.

Member of the IAB Tech Lab Agentic Taskforce, commenting in a personal capacity.

@KonstantinMirin

Copy link
Copy Markdown

Postindustria (IAB Tech Lab member). @aleksUIX, the arithmetic matches our fee-basis revision on #94. Four fixes so the texts agree:

  • Spend amount. "Payable to the seller" can read as seller_rate (§ 5.6), but the display example divides 80,000 by agreed_rate 24.00, not 20.40. "Pre-tax" settles #115's billing.tax_inclusive. Suggest: "amount is the seller total, on the same terms as agreed_rate, including selected delta_flat charges (§ 3.1)."
  • Fees. "Solely to make it additive" turns on intent. Suggest: "A seller fee is never a pricing[] entry."
  • Positive rate. Only the spend formula divides by it; the calculator also rejects a 0 CPM added-value line on basis = units. Scope it to basis = spend.
  • Bounds vectors. None fails min_spend or min_budget. Add a units case where only the fee meets min_spend: 400,000 impressions at USD 25 CPM plus USD 1,500 is USD 11,500, passing 11,000 and failing 12,000.

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

@aleksUIX

Copy link
Copy Markdown
Author

Updated in response to these four points. amount now uses the same terms as agreed_rate, leaving commission and tax treatment open. Seller fees cannot be separate pricing[] alternatives.

Zero-rate units commitments now work; spend still requires a positive agreed rate. Added fee-inclusive minimum-spend and minimum-budget cases: 400,000 impressions at USD 25 CPM plus USD 1,500 totals USD 11,500, passing 11,000 and failing 12,000.

All 60 calculation vectors pass, along with the appendix and YAML checks. The calculator remains a limited discussion profile; it does not establish acceptance or implement tax-inclusive arithmetic.

@KonstantinMirin

Copy link
Copy Markdown

Postindustria (IAB Tech Lab member). @aleksUIX, our pricing PR merges this PR and changes the adapter, vectors, and discussion document:

  • Names. gross_rate, floor, and delta_pct become list_rate, min_rate, and delta_fraction. min_budget, max_budget, and min_spend become the commitment_bounds.spend range. min_impressions and max_impressions become pricing[].unit_bounds. The input currency and the currency_mismatch vector go.
  • CPM-only bound. It goes: unit_bounds counts the committed entry's own unit on CPM, CPMV, and CPC.
  • delta_cpm. § 3.1 rejects only an option priced only by delta_cpm. A CPC entry keeps that option's other deltas.
  • Rounding and case. agreed_rate rounds once, half up, to 6 places, and derived_units rounds down. cost_method is case-sensitive.
  • accepted_counter. It goes, with selection_key: a granted rate is the next version's list_rate, so option deltas apply to it.

The discussion document keeps three proposals: no second charge for a cost in the unit rate, the sign rules, and the rounding limit. Could you review the merge there?

Open questions, also open questions 1 and 2 on our pricing PR:

  1. Your adapter treats a counter as the final composed rate. In our PR, a granted USD 21.50 with USD 8.50 in option deltas gives USD 30, and a 0.20 delta_fraction makes it USD 36. Is there a case that needs a final rate the deltas don't touch, such as a negotiated all-in price?
  2. Should § 5.6.5 state your sign rules for agreed_rate? A rate of 0 under spend gives no derived_units.

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

@aleksUIX

aleksUIX commented Nov 5, 2026

Copy link
Copy Markdown
Author

Reviewed the merge at e484091. Your list matches what the adapter and vectors do, and § 5.6.5 carries the fee arithmetic as #117 had it. All 60 vectors, check_examples.py and check_appendix.py pass locally.

Two stale spots in the discussion document: the derived_units formula on line 54 lacks the round-down that line 105 and § 5.6.5 state, and lines 59 and 73 still call the units informative, while § 5.6.1 now makes derived_units the committed units.

  1. The base-rate reading works, since list_rate is the rate before options and nothing adds deltas twice. The case it doesn't cover cleanly is a counter on the composed rate for a bundle, which the seller comment on [Change] § 5.6 — Give the buyer's counter a field (requested_rate), state how agreed_rate is derived, and say who can read floor and seller_rate #30 called closer to how direct-sales counters are made. Back-solving list_rate has two gaps. The grant stays in force if the buyer later drops an option, so a price given for the bundle applies without it. And with a delta_fraction, list_rate can need more places than agreed_rate keeps: with USD 8.50 in delta_cpm and 0.15, 17.586956 gives 29.999999 and 17.586957 gives 30.000001, so only a figure like 17.5869565 lands on 30. § 3.1 already has the all-in form: list_rate 30 with the negotiated options in included[], which carry no delta and don't lower the rate when dropped. The gap is procedural. A publish that changes included[] makes the open ask stale, and § 4.1.3 doesn't say a counter may change more than the asked value. One sentence letting a counter of list_rate also change included[], with paths[] naming both, would cover it. With that, dropping accepted_counter and selection_key is fine.

  2. Yes. The spec, checker and vectors disagree today: § 5.6.5 says only that derived_units is absent at a rate of 0 or below, check_examples.py accepts that commitment, and the zero-rate, negative-rate and negative-rate-units vectors reject it. Suggested text:

`agreed_rate` MUST NOT be negative. When `commitment.basis` is `spend`, on an
entry other than `FLAT` or `TIME`, `agreed_rate` MUST be greater than 0.

FLAT and TIME don't divide by the rate, so a commitment to the bonus example's FLAT 0.00 entry stays valid, and a units commitment can still be 0 for added value. The absent-derived_units sentence can then go, and check_examples.py would flag the case instead of skipping it.

I'll keep #117 as a draft until #146 lands and won't push to its branch.

@KonstantinMirin

Copy link
Copy Markdown

Thanks, @aleksUIX. #146 takes all of it, so you can check it there:

  • Sign rules: your text is in § 5.6.5, and the absent-derived_units sentence goes. scripts/check_examples.py flags a spend commitment with no rate, so spec, checker, and vectors agree.
  • Counter on a composed rate: § 4.3.1 lets a counter of list_rate also change included[], with paths[] naming both. Dropping accepted_counter and selection_key stands.
  • Discussion document: derived_units rounds down in the formula, and the units are no longer called informative.

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

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants