You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A DOOH impressions figure is never an observed event. It is plays × audience multiplier, where the multiplier comes from a measurement currency, a traffic study, the seller's own model, or — increasingly — an on-site sensor. AdCP already knows this (plays is documented as "raw play count before any impression multiplier is applied"; dooh_metrics.calculation_notes exists to explain the multiplier in prose) but gives a buyer no typed way to learn which kind of number impressions is. Two DOOH products at the same CPM — one on a 2019 traffic study, one on per-play sensor counts — are different products, and today they are indistinguishable on the wire.
Classic OOH already solved this for itself. ooh_metrics.estimation_basis (experimental in 3.2) is a closed tier enum, currency_measured | seller_modeled, with provider identity on the row-level measurement_source slug and a schema dependencies rule that makes the basis mandatory whenever the estimate is reported. This RFC extends that pattern to DOOH, adds the tier that sensors make possible, and exposes the basis at discovery time so buyers can compare before they buy.
Split out of #7150 (§3) per the discussion there; #7177 deliberately did not carry it. Supersedes the audience_multiplier line item from #5537, which closed without it.
What exists today
Surface
DOOH
Classic OOH
Raw unit
plays (top-level)
none — static units have no play event
Delivery number
impressions (top-level, modelled)
ooh_metrics.estimated_impressions
Basis tier
none
ooh_metrics.estimation_basis (currency_measured / seller_modeled), required when estimated_impressions present
Provider identity
row-level measurement_source slug (shared)
same
Methodology prose
dooh_metrics.calculation_notes
ooh_metrics.calculation_notes
Discovery-time declaration
dooh_placement_attributes (slot/loop duration, resolution, motion) — no basis
Hoist ooh_metrics.estimation_basis's inline enum to a shared file and add the tiers DOOH needs:
Value
Meaning
Provider identity
currency_measured
An audience-measurement currency's estimate for the unit and period (Geopath, Route, COMMB, MOVE, and their DOOH products)
measurement_source slug
seller_modeled
The seller's own model — traffic study, venue-attendance factor, historical footfall. The honest fallback.
the seller
sensor_measured
Audience derived from an on-site instrument observing presence per play — camera, WiFi/BLE, radar, turnstile, ticketing. Measured, not modelled, though the instrument has its own error.
the vendor_metric_values[] row it derives from (see basis_metric)
hybrid
A model calibrated by sensors: sensor counts on a sample of screens scale a currency or seller model across the network
measurement_source and/or basis_metric
Tier, not provider, not instrument. Currencies change and instruments are an open corpus (DR-0004) — both stay as data (measurement_source, the vendor catalog's methodology_url), not enum values. Four closed tiers is the same shape the OOH block already committed to.
impression_basis — the tier. SHOULD be present whenever a DOOH row reports impressions; proposed as a sales-dooh storyboard requirement once stable (mirrors OOH's dependencies rule, expressed on the parent since DOOH impressions is top-level).
audience_multiplier (number ≥ 0) — the effective impressions / plays for the row, declared, not inferred. Lets a verifier check impressions ≈ plays × audience_multiplier within tolerance and lets a buyer compare rows. For sensor_measured it is the realised ratio for the period, which will vary by row — that is the point.
basis_metric (optional { vendor, metric_id }) — when sensor_measured or hybrid, the vendor_metric_values[] row the audience figure derives from. This turns "impressions came from our cameras" into a join: the row carries coverage (measurable_plays), the seller–vendor relationship (vendor_relationship, feat(schema): typed vendor_relationship and play-based coverage denominators for vendor metrics #7177), and, via the vendor catalog, methodology_url / methodology_version / accreditations[]. No methodology prose is duplicated here.
venue_breakdown[] rows MAY carry impression_basis and audience_multiplier when the basis differs by venue (a mixed network: currency-measured roadside, sensor-measured retail).
Same enum, on the placement, with the same product-level-default / publisher-inheritance rule the block already uses for slot_duration_seconds. Optional audience_multiplier here is the planning value (what the seller's forecast will use). This is the half that changes buying: a buyer agent can filter or weight products by basis before create_media_buy, and get_products can grow a required_impression_basis filter later if demand appears (same filter-not-fail convention as required_vendor_metrics).
4. Forecast symmetry
delivery-forecast points already carry measurement_source and plays; add optional impression_basis so forecast and delivery reconcile on the same declaration, the way measurement_source already does.
5. Reuse, not duplication
ooh_metrics.estimation_basis switches its inline enum to the shared file. Renaming the OOH field to impression_basis is available while the block is experimental (Editorial-class under the experimental downgrade) — recommended for symmetry, WG's call.
delivery_measurement.notes and calculation_notes stay as row-specific prose. General methodology remains at the measurement catalog.
Non-goals
No new pricing_model. Billing stays CPM; what changes is that the CPM's basis is legible. A sensor_measured CPM and a seller_modeled CPM are different products at the same rate, and that is now visible.
Should impression_basis be required for the sales-dooh claim at 3.3, or SHOULD-only for one release? OOH chose required-by-dependency from day one.
Is a declared audience_multiplier acceptable to sellers whose multipliers are contractual with a currency provider? If not, the tier alone still carries most of the value.
Rename ooh_metrics.estimation_basis → impression_basis while experimental, or keep both names and share only the enum?
Release target
3.3. 3.2 is at rc.1 with a feature already landing in that candidate; this is a new normative surface the WG has not seen, and the OOH field it mirrors is itself experimental until 3.3. Interim path for sellers is unchanged: calculation_notes prose plus, for sensor networks, vendor_metric_values[] with vendor_relationship: "first_party" and measurable_plays (#7177, rc.1).
Summary
A DOOH
impressionsfigure is never an observed event. It isplays × audience multiplier, where the multiplier comes from a measurement currency, a traffic study, the seller's own model, or — increasingly — an on-site sensor. AdCP already knows this (playsis documented as "raw play count before any impression multiplier is applied";dooh_metrics.calculation_notesexists to explain the multiplier in prose) but gives a buyer no typed way to learn which kind of numberimpressionsis. Two DOOH products at the same CPM — one on a 2019 traffic study, one on per-play sensor counts — are different products, and today they are indistinguishable on the wire.Classic OOH already solved this for itself.
ooh_metrics.estimation_basis(experimental in 3.2) is a closed tier enum,currency_measured | seller_modeled, with provider identity on the row-levelmeasurement_sourceslug and a schemadependenciesrule that makes the basis mandatory whenever the estimate is reported. This RFC extends that pattern to DOOH, adds the tier that sensors make possible, and exposes the basis at discovery time so buyers can compare before they buy.Split out of #7150 (§3) per the discussion there; #7177 deliberately did not carry it. Supersedes the
audience_multiplierline item from #5537, which closed without it.What exists today
plays(top-level)impressions(top-level, modelled)ooh_metrics.estimated_impressionsooh_metrics.estimation_basis(currency_measured/seller_modeled), required whenestimated_impressionspresentmeasurement_sourceslug (shared)dooh_metrics.calculation_notesooh_metrics.calculation_notesdooh_placement_attributes(slot/loop duration, resolution, motion) — no basisdelivery_measurement.vendors[]+ deprecatedprovider+notesproseProposal
1. Shared basis enum —
enums/impression-estimation-basis.jsonHoist
ooh_metrics.estimation_basis's inline enum to a shared file and add the tiers DOOH needs:currency_measuredmeasurement_sourceslugseller_modeledsensor_measuredvendor_metric_values[]row it derives from (seebasis_metric)hybridmeasurement_sourceand/orbasis_metricTier, not provider, not instrument. Currencies change and instruments are an open corpus (DR-0004) — both stay as data (
measurement_source, the vendor catalog'smethodology_url), not enum values. Four closed tiers is the same shape the OOH block already committed to.2.
dooh_metrics.impression_basis(delivery){ "plays": 964984, "impressions": 1481441, "dooh_metrics": { "impression_basis": "sensor_measured", "audience_multiplier": 1.535, "basis_metric": { "vendor": { "domain": "dooh-seller.example" }, "metric_id": "people_in_frame" }, "loop_plays": 964984, "screens_used": 1894, "calculation_notes": "Per-play detected-person counts; screens with <10 plays fall back to venue model." }, "vendor_metric_values": [ { "vendor": { "domain": "dooh-seller.example" }, "metric_id": "people_in_frame", "value": 1481441, "unit": "persons", "measurable_plays": 964984, "vendor_relationship": "first_party" } ] }impression_basis— the tier. SHOULD be present whenever a DOOH row reportsimpressions; proposed as asales-doohstoryboard requirement once stable (mirrors OOH'sdependenciesrule, expressed on the parent since DOOHimpressionsis top-level).audience_multiplier(number ≥ 0) — the effectiveimpressions / playsfor the row, declared, not inferred. Lets a verifier checkimpressions ≈ plays × audience_multiplierwithin tolerance and lets a buyer compare rows. Forsensor_measuredit is the realised ratio for the period, which will vary by row — that is the point.basis_metric(optional{ vendor, metric_id }) — whensensor_measuredorhybrid, thevendor_metric_values[]row the audience figure derives from. This turns "impressions came from our cameras" into a join: the row carries coverage (measurable_plays), the seller–vendor relationship (vendor_relationship, feat(schema): typed vendor_relationship and play-based coverage denominators for vendor metrics #7177), and, via the vendor catalog,methodology_url/methodology_version/accreditations[]. No methodology prose is duplicated here.venue_breakdown[]rows MAY carryimpression_basisandaudience_multiplierwhen the basis differs by venue (a mixed network: currency-measured roadside, sensor-measured retail).3.
dooh_placement_attributes.impression_basis(discovery)Same enum, on the placement, with the same product-level-default / publisher-inheritance rule the block already uses for
slot_duration_seconds. Optionalaudience_multiplierhere is the planning value (what the seller's forecast will use). This is the half that changes buying: a buyer agent can filter or weight products by basis beforecreate_media_buy, andget_productscan grow arequired_impression_basisfilter later if demand appears (same filter-not-fail convention asrequired_vendor_metrics).4. Forecast symmetry
delivery-forecastpoints already carrymeasurement_sourceandplays; add optionalimpression_basisso forecast and delivery reconcile on the same declaration, the waymeasurement_sourcealready does.5. Reuse, not duplication
ooh_metrics.estimation_basisswitches its inline enum to the shared file. Renaming the OOH field toimpression_basisis available while the block is experimental (Editorial-class under the experimental downgrade) — recommended for symmetry, WG's call.delivery_measurement.notesandcalculation_notesstay as row-specific prose. General methodology remains at the measurement catalog.Non-goals
pricing_model. Billing stays CPM; what changes is that the CPM's basis is legible. Asensor_measuredCPM and aseller_modeledCPM are different products at the same rate, and that is now visible.vendor_metric_values[]rows (RFC: verified attention as a reportable vendor metric #7150 §5).Open questions for the WG
hybridload-bearing, or does every hybrid collapse to "whichever tier the majority of impressions came from" pluscalculation_notes? Place-based audio (RFC: Support place-based audio as DOOH inventory, not screen-only or generic streaming audio #5878) is the test case: presence sensing exists but is sparse.impression_basisbe required for thesales-doohclaim at 3.3, or SHOULD-only for one release? OOH chose required-by-dependency from day one.audience_multiplieracceptable to sellers whose multipliers are contractual with a currency provider? If not, the tier alone still carries most of the value.ooh_metrics.estimation_basis→impression_basiswhile experimental, or keep both names and share only the enum?Release target
3.3. 3.2 is at rc.1 with a feature already landing in that candidate; this is a new normative surface the WG has not seen, and the OOH field it mirrors is itself experimental until 3.3. Interim path for sellers is unchanged:
calculation_notesprose plus, for sensor networks,vendor_metric_values[]withvendor_relationship: "first_party"andmeasurable_plays(#7177, rc.1).Related
audience_multiplierproposed onPlacement, closed without itbasis_metricvendors)dooh_metricsis open, so these are patch-shaped additions structurally, minor by policycc @snehdhruv (Trillboards — the sensor_measured case), @geneticallymodifiedfoodforthought (place-based audio)