Skip to content

Measurement maturation windows for broadcast TV #2039

Description

@bokelley

Parent: #1919
Related: #1964 (media buy terms for measurement determinism), #1972 (measurement agents)

Problem

Broadcast TV measurement is fundamentally different from digital measurement. It's not "delayed data" — it's a measurement that matures over time.

Per Greg (O-N-X): "Fed-duplicated impression data accounts for Live + 7-day DVR printed measurements. We guarantee and reconcile as it comes in." Data arrives ~15 days after broadcast.

How broadcast measurement works

  1. Live: Impressions from viewers watching the broadcast in real-time
  2. Live + Same Day (LSD): Adds same-day DVR playback
  3. C3: Live + 3 days of DVR playback (standard for cable network guarantees)
  4. C7 / Live+7: Live + 7 days of DVR playback (increasingly the guarantee basis)
  5. Data arrives ~15 days later: The measurement vendor (VideoAmp, Nielsen, Comscore) processes set-top box data, smart TV ACR data, and panel data, deduplicates across sources ("fed-duplicated"), and delivers unified numbers

The current protocol handles this poorly:

  • expected_delay_minutes treats this as latency, not maturation. 15 days = 21,600 minutes, which technically works but misrepresents what's happening.
  • reporting_capabilities has no concept of a measurement window that grows.
  • delivery-metrics has no way to indicate "these are C3 numbers" vs "these are C7 numbers."
  • The reconciliation model assumes data stabilizes after a delay. Broadcast data doesn't stabilize — it accumulates through defined windows, then closes.

Proposal

Measurement window on reporting capabilities

Extend reporting-capabilities.json with an optional measurement_windows array:

{
  "measurement_windows": [
    {
      "window_id": "live",
      "description": "Live broadcast impressions only",
      "duration_days": 0,
      "expected_availability_days": 15,
      "is_guarantee_basis": false
    },
    {
      "window_id": "c3",
      "description": "Live plus 3 days of time-shifted viewing",
      "duration_days": 3,
      "expected_availability_days": 18,
      "is_guarantee_basis": false
    },
    {
      "window_id": "c7",
      "description": "Live plus 7 days of time-shifted viewing",
      "duration_days": 7,
      "expected_availability_days": 22,
      "is_guarantee_basis": true
    }
  ]
}

Window reference on delivery metrics

When reporting delivery, the seller indicates which measurement window the numbers represent:

{
  "measurement_window": "c7",
  "impressions": 1250000,
  "is_final": true
}

Guarantee basis on measurement terms

Extend measurement-terms.json so the guaranteed metric references a specific window:

{
  "billing_measurement": {
    "vendor": { "domain": "videoamp.com" },
    "measurement_window": "c7",
    "max_variance_percent": 10
  }
}

This tells both sides: "VideoAmp's C7 numbers are what we reconcile against."

3.0 case

This is the judgment call. Arguments for 3.0:

  • Structural: The concept of measurement maturation doesn't exist in the protocol. Adding it later means every broadcast implementation built on 3.0 used expected_delay_minutes as a workaround, and we'd need to migrate them.
  • The guarantee basis matters: Broadcast buys are guaranteed on specific windows (C3 or C7). Without measurement_window on the terms, there's no way to express what the guarantee is actually measured against.
  • Greg's workflow depends on it: "We guarantee and reconcile as it comes in" — the data arrives incrementally as windows close. The protocol needs to represent which window a given set of numbers corresponds to.

Arguments for 3.1:

  • Complexity: This touches reporting-capabilities, delivery-metrics, and measurement-terms — three schemas.
  • Could use ext: Broadcast sellers could put ext.measurement_window: "c7" on delivery reports and terms as a stopgap.
  • Small seller count initially: Only a few broadcast sellers are launching on AdCP in 3.0.

My recommendation: 3.0 for the measurement_window concept (the enum and references on terms/delivery), 3.1 for the full maturation lifecycle (provisional counts, window progression, detailed reconciliation rules).

Open questions

  • Is measurement_windows on the product (seller declares available windows) or on the terms (negotiated per buy)?
  • Should the protocol define standard window IDs (live, lsd, c3, c7) or let sellers define their own?
  • How do we represent "numbers updated — same window, better data" vs "new window available"?
  • Does is_final need to be per-window rather than per-report?

Metadata

Metadata

Assignees

No one assigned

    Labels

    rfcProtocol change — auto-adds to roadmap board

    Type

    No type

    Projects

    Status
    Shipped

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions