Skip to content

[Change] § 5.2, § 5.5 — DOOH properties: venue type, screens, operating hours, and loop #96

Open

Description

@KonstantinMirin

What kind of change?

Change a field's type or shape

Which section?

5.2 — Inventory composition

Current text

§ 5.2: | `properties` | Object | selectable | `available[]` of `{ id, name, domains, supported_formats }`, `included[]`, `pricing`, `max_select` |

§ 5.5: | `frequency_cap` | Object | settable | `{ max: { min, max }, period, basis: device \| household \| listener }`. Basis matters: CTV typically caps at household, audio at listener |

§ 5.6: | `availability` | Object | derived | `{ unit, basis, as_of, granularity, type: forecast \| reservable, quantity }`. Recomputed against the buyer's selection |

§ 5.9: | `serving_mode` | Enum | seller-set | `client_side` \| `ssai` \| `dai` |

Proposed text

§ 5.2, `properties` row: add `venue_type, allocation, screens, min_screens,
slots_per_loop, sync_groups` to the `available[]` keys.

Add after the table:

**DOOH properties.** When `channel` is `dooh`, a property is a set of
screens of one venue type, `domains` holds the inventory owner's domain (as
OpenRTB 2.6 `dooh.domain`), and `venue_type` is REQUIRED. `screens` is
REQUIRED when `allocation` is `all`.

| Key | Meaning |
| :--- | :--- |
| `venue_type` | `{ taxonomy, ids[] }`. `taxonomy` is a value of AdCOM 1.0 List: DOOH Venue Taxonomies; `ids[]` holds exactly one id in that taxonomy, which covers only itself, not its descendants. The values OpenRTB 2.6 `dooh.venuetypetax` and `dooh.venuetype` carry |
| `allocation` | `all` (default) or `seller_allocated`. With `all`, the line item runs on every listed screen. With `seller_allocated`, the seller picks the screens: `screens`, when present, is the pool it picks from and is seller-set, and the proof-of-play log names the screens used |
| `min_screens` | With `seller_allocated`, the fewest screens the seller allocates to the line item |
| `screens` | Array of `{ screen_id, lat, lon, movable, time_zone, operating_hours, loop }`. `screen_id` is the seller's id for the screen, as its proof-of-play log carries it. When the bid request's `device.ifa_type` is `ppid`, `device.ifa` carries the same id. `lat` and `lon` are absent when `movable` is true |
| `operating_hours` | `{ days[], start, before }` windows, in the screen's IANA `time_zone`. `before` is the first minute after the window |
| `loop` | `{ length_s, slot_s }`: loop length and slot length. Absent when the screen schedules ads without a loop |
| `slots_per_loop` | The slots per loop the line item buys on each screen of the property that has a `loop` |
| `sync_groups` | Array of `{ sync_group_id, screen_ids[], min_screens_per_play }`: screens that show the same ad at the same moment, sold as one. `min_screens_per_play` is the fewest of the group's screens that must show a display for it to count as one play |

With `seller_allocated`, a buyer value MUST NOT name or exclude individual
screens.

The committed quantity is in the committed `pricing[]` entry's unit: `PLAY`
commits plays, and `CPM` commits impressions. The other count is
informative. With `seller_allocated`, or on a screen that schedules without
a loop, plays are also reported. A `committed_metrics[]` tuple commits its
own level either way.

With a `loop`, a screen delivers `slots_per_loop` × 3,600 ÷ `length_s` plays per
operating hour.

§ 5.5, `frequency_cap` row: replace `max: { min, max }` with `count`, and
`basis: device \| household \| listener` with `per`, a core term or an
extension term `<domain>:<term>`.

After the table:

**Frequency cap `per`.** The core terms are `device`, `household`,
`listener`, and `screen`. `screen` caps plays per DOOH screen, counted by `screen_id`, or by `sync_group_id` for a sync group's screens; in
the bid stream, the screen is the OpenRTB 2.6 `device` with `devicetype` 8.

§ 5.6, `availability` row, append:

The `unit` core terms are the cost methods' units, such as `impressions`
and `plays`, and `slots_per_loop` and `unit_periods` (one unit for one period,
such as a board for a 4-week cycle). Extension terms are `<domain>:<term>`.
An `availability` compares with a commitment only in the committed entry's
unit.

§ 5.9, `serving_mode` row: add the core term `scheduled`, where the media
owner's scheduler pushes plays to the player.

§ 2.1, Summary Representation: add `properties.available[].venue_type`.

Why

A DOOH line item can name a screen as a property, but not its venue, location, operating hours, or loop. § 5.2 gives a property only an id, a name, domains, and formats.

Those four terms set the plays, and through the multiplier (our plays and impressions filing) the price. One 10-second slot in a 60-second loop, 06:00–24:00, gives 1,080 plays per screen-day. A buyer counting 18 hours on a mall screen open 10:00–21:00 expects 7 hours too many. This change drafts the loop and hours terms of #79.

Transit sellers also sell stations or lines and pick the screens, as #81 and #83 ask. allocation: seller_allocated covers that sale. As @premesh (OUTFRONT Media) explains on #79, a buyer who picks screens in a pooled product defeats the product. So a pool's screens are seller-set, and its impression goal is a CPM entry.

Venue sellers sell synchronized screens as one play, as @premesh explains on our plays and impressions filing; sync_groups names them. @premesh suggests folding them into this model.

The bid stream has these keys:

As @premesh (OUTFRONT Media) points out on #8, device | household | listener has no meaning on a one-to-many screen, so the change adds screen, with plays as the unit. per, the draft's basis, becomes an open vocabulary, as our cost-method filing (#94) makes cost_method, so a later term needs no revision.

@jaanijuk asks on #134 for core terms for availability.unit. @premesh lists the units sellers use on #8, and notes that serving_mode doesn't describe a media owner's scheduler. The cost methods' units are in our pricing PR, and the serving_mode core terms in our video and audio PR.

The MRC Out-of-Home Measurement Standards, Phase 1 & 2 Combined count plays per Loop and require: "Display operating times must be defined and factored into impression counts".

Details and examples: DOOH properties: full rationale and examples

Knock-on effects

Open questions for the working group

  1. When device.ifa_type is ppid, should device.ifa be REQUIRED to equal screen_id or only RECOMMENDED, and when it's sspid, should the exchange's id map to screen_id through device.eids or another way?
  2. Answered by @premesh on #8. On a dooh line item, should device mean the screen, as proposed, or should the cap gain an explicit screen term? The proposed text adds screen, and device keeps its own meaning.
  3. When a buyer's frequency_cap allows fewer plays than the bought slots_per_loop and loop deliver, should the cap lower the expected plays and units, or should the seller reject the selection as inconsistent?
  4. Should one line item be able to select both an all property and a seller_allocated property, or should every selected property share one allocation?
  5. When a DOOH inventory owner publishes no ads.txt at its domains entry, should the check in our seller relationship filing run through sellers.json and OpenRTB 2.6 dooh.publisher, or should the claim stay unverifiable, as that filing proposes?
  6. Should operating_hours carry dated exceptions, such as holiday closures, or should the proof-of-play log alone show the plays those days lose? This is open question 4 of our screen loop reply on #79.
  7. Should a screen cap count plays of each creative, or of all the line item's creatives together? @jaanijuk raises it.
  8. Answered in our shared types PR and our buyer writes PR. Which period values should frequency_cap take, and is each a calendar period or a rolling window? As @jaanijuk reports, a GAM mapping writes a day as "1 day", where their line item writes "day". The PRs make period one of hour, day, week, month, or flight, and every value but flight a calendar period in time_zone.
  9. How does a line item identify a taxonomy version that AdCOM 1.0 List: DOOH Venue Taxonomies doesn't list yet, such as OpenOOH 1.2.1? And does one version's taxonomy value cover later versions? AdCOM expects an entry to "refer to a specific version, unless a given taxonomy has explicit semantics for forward compatibility and handling updates". @jaanijuk raises both in #134.
  10. On a dooh line item, does a FLAT day count plays or impressions? Our rules issue asks implementers whether they need a rule.

Would this break an implementation already built to this draft?

Yes — breaking (a dooh property without venue_type, or sold whole without screens, no longer conforms)

Alternatives you considered and rejected

  • One line item per screen. Thousands of line items, and no package price.
  • One property per screen, with no new keys. The buyer still can't see venue, hours, or loop.
  • Venue type as a string. OpenOOH 1.1 deprecates strings.

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: Our shared types PR gives per and count, and drops catalog_ref, so screens are listed inline. Our buyer writes PR gives before, our DOOH PR slots_per_loop and sync_group_id, and our property option PR venue_type.ids[]. The committed quantity is in the committed entry's unit. Adds core unit terms and scheduled, from @jaanijuk on #134 and @premesh on #8. Answers open question 8, and adds 10.

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

Activity

  1. KonstantinMirin commented on Oct 23, 2026

    @KonstantinMirin
    Author

    Revision, from seller input on #79. @premesh (OUTFRONT Media) answered two of our open questions from how they sell. A pooled product and a fixed loop commit different units. A buyer who picks screens in a pooled product defeats the product.

    We revise the allocation row to:

    | `allocation` | `all` (default) or `seller_allocated`. With `all`, the line item runs on every listed screen. With `seller_allocated`, the seller picks the screens: `screens`, when present, is the pool it picks from and is seller-set, and the proof-of-play log names the screens used |
    
    With `seller_allocated`, a buyer value MUST NOT name or exclude individual
    screens.
    
    The committed quantity follows the product:
    
    - `allocation: all`, screens with a `loop`: plays are committed, verified by
      `proof_of_play`; impressions are informative.
    - `allocation: seller_allocated`: impressions are committed against the
      controlling measurement; plays are informative and reported.
    - A screen that schedules without a loop: impressions are committed; plays
      are reported.

    This replaces "delivery is counted in plays or impressions across the pool". The play and impression definitions are in our plays and impressions change request (#92). The controlling measurement is in our settlement change request (#95) and measurement source per committed metric (#38). The matching share-of-voice basis is on our delivery type change request (#93).

    Open question 4 of our reply on #79 stays open: should operating_hours carry dated exceptions, such as holiday closures, or should the proof-of-play log alone show the plays those days lose?

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

  2. esteininger commented on Oct 23, 2026

    @esteininger

    Commenting as a content classification vendor (Mixpeek). Cites v3.0-draft-1.

    Support the property shape here. One gap for buyers who care about adjacency: the
    property says where the screen is and how the loop runs, but not what else plays in the
    loop. A transit screen that runs news headlines and one that runs sports highlights look
    identical in the proposal.

    #48 proposes content_categories.declared[] on inventory with a version-pinned
    taxonomy_ref (IAB Content Taxonomy 3.1 maps to AdCOM cattax 9). For DOOH it would sit
    on the property, or per screen when screens in one property run different loops, and
    classification.method: model covers the case where the categories come from
    classifying the loop's editorial content rather than a seller label. The same ids can
    then travel in the bid request, so discovery and execution agree.

    Suggest #96 notes that content_categories (if accepted) applies to DOOH properties, at
    property or screen level.

  3. KonstantinMirin commented on Oct 25, 2026

    @KonstantinMirin
    Author

    Thank you, @esteininger. Agreed, as a knock-on of this filing. Your content categories on inventory (#48) puts content_categories on the line item. We'll add this to the filing as a knock-on: if the working group accepts #48, content_categories, in #48's shape, joins the DOOH property keys. Categories sit on the property only. Screens that show different content around the ad are a separate property, as screens of different venue types are, so nothing combines under the no-inheritance rule (§ 2). This matches the bid stream: a DOOH bid request can carry what plays on its screen in OpenRTB 2.6 dooh.content, as cat with cattax.

    Following @premesh's answer on #8, this revision also makes frequency_cap.basis an open vocabulary, as our cost-method filing (#94) does for cost_method, and adds screen as a core term for DOOH.

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

  4. jaanijuk commented on Oct 28, 2026

    @jaanijuk

    Implementation evidence for this change's basis revision, which we support: screen as a core term, and extension terms written <domain>:<term>. From IAB Australia's AAMP lab: an unreleased seller-agent branch (IABTechLab/seller-agent, feat/openproposal-mapping at e77022e), synthetic data, three runs across two environments with byte-identical results. #134 has the details.

    • The branch's line-item model types basis and period as free strings. It accepted basis: "screen" on our DOOH line item, but it would accept any other string too. The revision's rule, a core term or <domain>:<term>, gives an implementation something to check.
    • Its GAM mappings report the gap from the ad-server side: "frequency_cap.basis: GAM caps per user; OpenProposal wants device, household or listener". They leave basis unset.
    • The same mappings write period as "1 day", from GAM's one-day time unit, where our DOOH line item used "day". The model accepted both.
    • Against draft 1, the independent schema from [Impl] A schema can't be derived from the tables yet: seven authoring rules and a CI lint would fix that #121 rejects a bare "screen" and accepts a namespaced term (checked with Python jsonschema 4.26.0): the rule the revision now writes into § 5.5.

    Two points § 5.5 still leaves open:

    1. Scope. Whether a screen cap counts plays of one creative or of all the line item's creatives.
    2. Period. The period values, and whether each is a calendar period or a rolling window. GAM's one-day unit and a hand-written line item already write a day differently.
  5. ChaitanyaKumarSeri commented on Nov 11, 2026

    @ChaitanyaKumarSeri

    Commenter: Chaitanya Kumar Seri, Associate Director of Product Management, Best Buy Ads. Previously Principal Product Manager at Amazon Ads and in-store retail media product leadership at Walmart Connect. Commenting in a personal capacity, drawing on seller-side product experience.

    Relevant sections: § 5.2, § 5.4, § 5.5 and § 5.6, together with the proposed changes in #93, #96 and #148.

    I support the DOOH inventory work in #96 and #148, including the distinction between named-screen delivery and seller-allocated pools. I also support keeping creative specifications in the format structure discussed in #5 and #152, with inventory and commercial terms separately defined.

    For in-store retail media, I recommend the following refinements and worked examples.

    1. Identify the placement within the store.

    A venue classification and geographic coordinates do not fully describe an in-store placement. An entrance display, a television wall, a product-category screen and a checkout screen may share the same store address while offering different exposure opportunities.

    Please define an explicit association between the store or venue identifier, placement zone and relevant screen or synchronized group. The exact field names can follow the working group’s preferred structure, but a buyer should not have to infer the placement zone from a property name or free-text description. Store coverage and physical screen count should also remain separately identifiable.

    1. Make the share-of-voice denominator explicit in retail examples.

    The distinction in #93 between loop-time share and impression share is useful. A retail example should also address loops containing retailer content, product demonstrations and paid advertising.

    For example, a 300-second loop might contain 60 seconds of paid advertising. One 15-second advertising slot represents 5% of the complete loop but 25% of the paid advertising time. Both percentages can describe the same placement.

    For the proposed loop_time basis, the example should explicitly use the complete loop as the denominator. Any percentage based only on paid advertising time should be separately labelled and should not be substituted for the loop-time share. The applicable screens, flight and daypart should remain attached to the calculation.

    1. Include known calendar exceptions before commitment.

    On the open question about dated operating-hour exceptions, my recommendation is yes: known holiday closures, extended holiday hours and scheduled screen downtime should be expressible before commitment.

    Proof-of-play establishes what subsequently ran. It cannot correct a planning assumption that already included hours when the store was known to be closed. Unexpected outages can remain subject to the agreed delivery and shortfall terms.

    1. Validate the selected creative against the inventory actually promised.

    A network can contain landscape walls, portrait displays and screens with different audio or duration restrictions. Where every named screen is promised, the selected creative must be compatible with that entire set. In a seller-allocated pool, the proposal should make the compatible eligible pool clear and preserve the promised minimum coverage.

    1. Add an in-store worked example.

    Please include a fictional example with multiple placement zones, a synchronized television wall, a holiday-hours exception and a buyer-selected daypart. It should show how the selection affects eligible screens, scheduled plays, share of voice and the audience estimate.

    This would give implementers a concrete way to check that an offer remains interpretable and deliverable as the buyer changes its composition.

  6. jaanijuk commented on Nov 11, 2026

    @jaanijuk

    Thanks for raising these. Two of your points connect directly to our Australian pilot checks, and your mixed-content loop example raises a question our test didn’t cover.

    3. Dated exceptions. In our synthetic example on #148, the checker accepted a commitment of 8,610 impressions on a screen with 35 operable hours. The follow-up discussion put the availability check with the agents. That makes your holiday example particularly relevant to question 6 here. If a store normally opens on Tuesdays but closes on one specific Tuesday, how should the seller express that exception, and how can the buyer tell whether the quoted availability already accounts for it? Availability discussion on #148

    4. Creative requirements by screen. We tried putting a creative_policy on one screen within a property. The checker rejected it at 56cbd4da, and we saw the same result at b718eb5b. Your example gives that finding a practical consequence. When a restriction applies to only some of the promised screens, how should a buyer identify which screens can carry its creative? Our screen-level check on #134, item 3

    2. Share-of-voice denominator. Our 70-second example didn’t say what the rest of the loop held, so it never separated loop time from paid ad time. Your example separates them. It would help if the definition of length_s said explicitly whether it includes unpaid content. Then a buyer and seller could reproduce the same percentage from the same schedule. Loop-time proposal on #93

    Edited 13 Nov 2026: two corrections. “35 operating hours” is now “35 operable hours”, and the loop sentence no longer says our example was all ads; it didn’t record what the rest of the loop held.

  7. KonstantinMirin commented on Nov 11, 2026

    @KonstantinMirin
    Author

    Thanks, @ChaitanyaKumarSeri, for the in-store detail, and @jaanijuk, for tying it to your checks. #148 carries this change.

    Share-of-voice denominator. #148 counts slots_per_loop × 3,600 ÷ length_s plays an hour, which holds only if length_s is the whole loop. It now says so: loop length counts every item the loop plays, paid or not (§ 5.2, count every item a DOOH loop plays in its length). The loop_time share is slots_per_loop × slot_s ÷ length_s, so a 15-second slot in a 300-second loop is 5% (§ 5.9).

    Creative by screen. Formats are on the line item (§ 5.4), and a screen has no creative_policy of its own. With allocation: all, the line item runs on every listed screen, so we read that as every listed screen taking the formats in effect. #148 doesn't yet tie a seller_allocated pool, or its min_screens, to the formats. Either way, a seller whose screens and formats don't combine publishes separate line items (§ 3.1).

    Dated exceptions. #148 can't state one yet, so a buyer can't tell whether a figure allows for it. It's open question 6 here, and yours is the first seller answer. We'd leave its shape to the working group.

    Placement zones and an in-store example. #148 has neither a zone key nor an in-store example. We'd leave both to the working group too.

    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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions