Trillboards OpenRTB 2.6 Extension Schema Reference

version 2026-03-v1

Schema reference for Trillboards' proprietary OpenRTB 2.6 bid request extensions. This is NOT a bid endpoint specification — it documents the SIGNALS injected into every bid request sent to DSPs so engineers can build bidding algorithms that leverage Trillboards' unique audience intelligence.

How to Use This Document

When Trillboards sends a bid request to your DSP, it includes standard OpenRTB 2.6 fields plus the proprietary extensions documented here. Your bidding algorithm can use these signals to bid higher on high-value inventory.

Extension Namespaces

NamespaceWhat It ContainsFreshness
ext.trillboardsReal-time audience signals from FEIN edge AI10-30 seconds
ext.trb.vasVerified Attention Seconds (historical quality)7-day rolling
ext.trb.intentPurchase intent from speech analysis10-30 seconds
ext.trb.weatherContextual weather conditions60-minute cache
ext.trb.foot_trafficVenue occupancy and traffic10-30 seconds
ext.trillboards_contractSignal quality assurancePer-request
user.data[]IAB Audience Taxonomy 1.1 segments + seller-defined10-30 seconds

Signal Sources

Data behind the signals


Schemas

30 schemas. Every one is derived from docs/openapi/openrtb-extensions.yaml at request time.

AudienceAttentionPrediction · AudienceSocialAttention · BidRequestExt · CompletedImpressions · ContractExt · DOOHBidRequest · DOOHObject · DemandPartners · Device · EarnerScreens · EventExt · FootTrafficExt · IABSegmentReference · Impression · IntentExt · OpenrtbRevenueScreenHourly · PartnerReconciliationReports · PartnerVariants · PartnerZoneCpmDaily · Regs · Segment · SellerDefinedSegmentReference · Source · TrbNamespace · TrillboardsAudienceExt · User · UserData · VASExt · VenueExt · WeatherExt

AudienceAttentionPrediction

Backend-derived predictive attention signal + buyer-grade attentive-seconds. 1:1 with audience_metrics. Never null by contract; placeholder on row 1.

PropertyTypeRequiredDescription
predicted_attention_next_30sstring — one of high, medium, low, noneyespredicted_attention_next_30s enum {high,medium,low,none}. 'none' is below 'low'; fires when rolling history converges to zero or on a trend down from 'low'.
predicted_disengagement_imminentbooleanyespredicted_disengagement_imminent needs elevated dwell AND a falling trend, so it is unreachable whenever the history vector is empty. A 0% fire rate is a HISTORY-PLUMBING alarm, not a quiet fleet.
prediction_evidencestringyes
attentive_seconds_observednumberyesattentive_seconds_observed = SUM(per_face[].gaze_seconds >= 1.0), OpenOOH 2024 4.2. NEVER NULL by DDL, so 0.000 means 'no viewer met threshold' ONLY when per_face_observations[] was present. NUMERIC(6,3).
attentive_face_countintegeryesattentive_face_count SMALLINT: distinct viewers meeting the >=1s threshold; the buyer-side CPMA denominator. NEVER NULL.
attentive_seconds_predicted_15snumberyesattentive_seconds_predicted_15s: expected next-15s attentive seconds from per-screen history x attention-weight; bootstrap = linear extrapolation. No global tau. NUMERIC(6,3).
next_state_attention_forecastnumber, nullable
next_state_confidencenumber, nullable
next_state_methodstring, nullable
next_state_horizon_minutesinteger, nullable
next_state_sample_sizeinteger, nullable
next_state_forecast_atstring, nullable
next_state_attention_realizednumber, nullable
next_state_abs_errornumber, nullable
next_state_graded_atstring, nullable
next_state_persist_abs_errornumber, nullable
next_state_xscreen_abs_errornumber, nullable
next_state_xscreen_sample_sizeinteger, nullable
next_state_xscreen_methodstring, nullable
next_state_xsv_abs_errornumber, nullable
next_state_xsv_sample_sizeinteger, nullable

AudienceSocialAttention

Buyer-grade social amplification signal (5 typed columns). Cloud Vertex Gemini producer. 1 row per audience observation when cascade is observable.

PropertyTypeRequiredDescription
social_amplification_factornumberyesNUMERIC(4,3).
cascade_depthintegeryes
viral_attention_scorenumberyesviral_attention_score is the headline number Viant/T-Vision license. Composite of social_amplification_factor × cascade_depth × emotional engagement. NUMERIC(4,3).
primary_attention_anchor_face_indexinteger, nullableAll 5 columns NOT NULL except primary_attention_anchor_face_index (only legit NULL: no anchor or solo scene).
amplification_evidencestringyes
data_projection_versionintegeryes
data_projection_xidstringyes

BidRequestExt

Top-level bid request extensions.

⚠️ Both Trillboards namespaces are STRIPPED on curated (registered-audience) deals

When a bid request is served under a curation plan with registeredAudienceOnly — the shape behind our curated PMP / registered audience deals — the server deletes ext.trillboards and ext.trb outright before the request leaves us (services/programmatic/bidstreamSignalCuration.js). If ext is left with no other keys, ext itself is removed.

This is deliberate: on a curated deal the audience is carried by the registered segment in user.data, and the raw sensing signals are withheld.

The consequence for a bidder is the trap worth stating plainly: every signal described on this page disappears on exactly the deals we most want you buying. A bidder whose valuation depends on ext.trb.vas, ext.trillboards.attention_score, or any other field here will price curated inventory as though the screen had no audience at all.

Build for this explicitly:

PropertyTypeRequiredDescription
protocolstring
trillboardsTrillboardsAudienceExt
trbTrbNamespace
trillboards_contractContractExt

CompletedImpressions

Completed-play observations from VAST complete and proof-of-play paths. Deduped by issued request/impression key for live revenue and daily earnings.

PropertyTypeRequiredDescription
idinteger, nullableJustBaat dedupes issued request keys; Adipolo/VidVerto/others use rendered impression_id with request fallback. Readers/rollups dedupe overlapping vast_event, proof_of_play and approved partner_sdk.
completed_atstringyes
screen_mongo_idstringyes
device_idstring, nullable
ad_idstringyes
creative_idstring, nullable
impression_idstring, nullable
source_providerstringyesImpressionController drops rows with unknown source_provider (PR #2924); earnings use partner billing policy, not raw counts. Exclude pi_e2e_*, admin-allocation and is_demo_data from revenue.
variant_namestring, nullable
actual_cpmnumber, nullableNUMERIC(18,6).
actual_gross_revenuenumber, nullableNUMERIC(18,6).
pricing_sourcestringyesPG is the canonical completion write; completed_impressions_dist is its CH reporting mirror. pricing_source: 'placement_purchase'=ad_price/goal per play; '_overdelivered'/'_zero'=$0; 'config_defa...
currencystringyes
ingestion_pathstringyes
request_idstring, nullableowned_direct = signed src or verified SDK. VAST impid, request_id and SDK suffix share one nonce/PG row; completion, exact debit and eligible billing commit together. First authorized write owns CH...
bid_request_idstring, nullable
play_idstring, nullable
duration_secondsnumber, nullableNUMERIC(10,2).
givt_passedboolean, nullable
signaturestring, nullable
display_modestring, nullable
display_area_rationumber, nullableNUMERIC(5,4).
metadataobjectyesSDK missing-price is server-pending until signed native pricing; directbillable_ is not authority. Client debit/mirror/pending claims are stripped. Legacy finalization: recorded/native nonnull zero...
created_atstringyeschEventParityCron: exact-key repair; created_at/oldest authorized floor; original completed_at CH key; same writer/DLQ before ACK; no delivery debit. All leaf pending indexes must be valid; failed/...
screen_idinteger, nullable
demand_partner_idinteger, nullable
variant_idinteger, nullable
content_sha256string, nullablecontent_sha256 is DECLARED to propagate from vast_requests via request_id but lands on ~1% of rows: PG vast_requests is empty (vastRequestsWriteBuffer defaultDisabled since 2026-06-26), so that lin...
serving_tenant_idinteger, nullable
impression_multipliernumberyesNUMERIC(12,6).
quantity_sourcestring, nullable
quantity_source_typeinteger, nullable
quantity_vendorstring, nullable
quantity_measured_atstring, nullable
earnings_sourcestring, nullable
earnings_deal_idstring, nullable
earnings_deal_typestring, nullable
advertiser_domainstring, nullable
buyer_seatstring, nullable
zone_idstring, nullable
raw_client_timestampstring, nullable
normalized_event_timestampstring, nullable
event_clock_skew_secondsnumber, nullable
event_timestamp_clampedboolean, nullable
billable_keystring, nullable

ContractExt

Signal quality assurance contract. Tells DSPs how complete and reliable the signals in this bid request are. If valid=false, some required fields are missing (but the request is still valid OpenRTB).

PropertyTypeRequiredDescription
versionstringContract schema version
validbooleanWhether all required fields passed validation
required_field_coverage_pctnumberPercentage of required fields that are present and valid
error_countintegerNumber of validation errors (missing required fields)
warning_countintegerNumber of validation warnings (recommended fields missing)
errorsarray of object
warningsarray of object

{
  "version": "2026-03-v1",
  "valid": true,
  "required_field_coverage_pct": 100,
  "error_count": 0,
  "warning_count": 0,
  "errors": [],
  "warnings": []
}

DOOHBidRequest

Full OpenRTB 2.6 DOOH bid request with all Trillboards extensions

PropertyTypeRequiredDescription
idstringUnique bid request ID
imparray of Impression
doohDOOHObject
deviceDevice
userUser
sourceSource
regsRegs
atinteger — one of 1Auction type. Always 1 (first price)
tmaxintegerMaximum response time in milliseconds
curarray of string
extBidRequestExt

{
  "id": "691fced1-040c-4354-b861-ef2496f44f29",
  "imp": [
    {
      "id": "imp_507f1f77bcf86cd799439011",
      "tagid": "507f1f77bcf86cd799439011",
      "bidfloor": 2,
      "bidfloorcur": "USD",
      "secure": 1,
      "dt": 1788279423607,
      "qty": {
        "multiplier": 2,
        "sourcetype": 2
      },
      "banner": {
        "w": 1920,
        "h": 1080,
        "format": [
          {
            "w": 1920,
            "h": 1080
          }
        ],
        "pos": 1
      },
      "video": {
        "mimes": [
          "video/mp4",
          "video/webm"
        ],
        "minduration": 5,
        "maxduration": 30,
        "protocols": [
          2,
          3,
          5,
          6
        ],
        "w": 1920,
        "h": 1080,
        "startdelay": 0,
        "linearity": 1,
        "skip": 0,
        "placement": 4
      }
    }
  ],
  "dooh": {
    "id": "507f1f77bcf86cd799439011",
    "name": "Test Screen",
    "venuetype": [
      2,
      202
    ],
    "venuetypetax": 5,
    "publisher": {
      "id": "trillboards",
      "name": "Trillboards",
      "domain": "trillboards.com",
      "cat": [
        "IAB24"
      ]
    },
    "domain": "trillboards.com",
    "keywords": "Retail,Shopping Mall,New York,NY",
    "content": {
      "genre": "Entertainment",
      "cattax": 1,
      "cat": [
        "IAB1"
      ],
      "prodq": 1,
      "context": 1,
      "contentrating": "TV-PG",
      "livestream": 1,
      "language": "EN",
      "channel": {
        "name": "Entertainment"
      }
    }
  },
  "device": {
    "devicetype": 8,
    "connectiontype": 2,
    "w": 1920,
    "h": 1080,
    "geo": {
      "lat": 40.7128,
      "lon": -74.006,
      "type": 1,
      "country": "US",
      "region": "NY",
      "city": "New York",
      "zip": "10001"
    }
  },
  "source": {
    "fd": 0,
    "tid": "691fced1-040c-4354-b861-ef2496f44f29",
    "schain": {
      "complete": 1,
      "nodes": [
        {
          "asi": "trillboards.com",
          "sid": "trillboards",
          "rid": "691fced1-040c-4354-b861-ef2496f44f29",
          "name": "Trillboards",
          "domain": "trillboards.com",
          "hp": 1
        }
      ],
      "ver": "1.0"
    }
  },
  "at": 1,
  "tmax": 500,
  "cur": [
    "USD"
  ],
  "test": 0,
  "regs": {
    "coppa": 0,
    "gdpr": 0
  },
  "ext": {
    "protocol": "OpenRTB 2.6",
    "trillboards_contract": {
      "version": "2026-03-v1",
      "valid": true,
      "required_field_coverage_pct": 100,
      "error_count": 0,
      "warning_count": 0,
      "errors": [],
      "warnings": []
    },
    "trillboards": {
      "attention_score": 0.87,
      "audience_count": 8,
      "crowd_density": 12,
      "ad_receptivity": 0.75,
      "emotional_engagement": 0.82,
      "mood": "happy",
      "estimated_occupancy": 25,
      "avg_dwell_ms": 4500,
      "group_composition": {
        "solo": 3
      },
      "screen_engagement": "active",
      "audience_reaction": "positive",
      "signals_age_ms": 12480
    },
    "trb": {
      "weather": {
        "temp_f": 85,
        "feels_like_f": 88,
        "humidity": 75,
        "condition": "Partly cloudy",
        "uv_index": 8,
        "wind_mph": 12,
        "is_raining": false,
        "temp_segment": "hot"
      },
      "foot_traffic": {
        "current_audience": 25,
        "estimated_occupancy": 50,
        "avg_dwell_seconds": 6,
        "traffic_tier": "very_high",
        "estimated_hourly_impressions": 15000
      }
    }
  }
}

DOOHObject

OpenRTB 2.6 DOOH object (top-level, replaces site/app)

PropertyTypeRequiredDescription
idstring
namestring
venuetypearray of integerOpenOOH venue-type ids, as INTEGERS, projected down to taxonomy 1.1 — the version venuetypetax declares. Corrected 2026-09-01 against openrtbRequestBuilder.js, which has always emitted integers. This declared string items and "v1.2 IDs"; both were wrong. Our tables implement OpenOOH 1.2, but AdCOM's taxonomy enumeration stops at 5 (= OpenOOH 1.1), so 1.2 cannot be signalled on the wire at all and the ids are projected. The projection is lossless in MEANING, only in specificity — see the WIRE PROJECTION block in config/openoohTaxonomy.js. The array is OMITTED rather than sent empty when classification yields nothing: venuetype: [] would assert "we classified this screen as belonging to no venue type", which is a different and false claim.
venuetypetaxinteger — one of 5AdCOM venue-taxonomy identifier. 5 = OpenOOH 1.1, and 5 is what we send. Corrected 2026-09-01. This declared enum: [1] described as "1 = OpenOOH Venue Taxonomy". AdCOM value 1 is OpenOOH 1.0, so the published contract named the oldest taxonomy in the list while the ids alongside it were not that taxonomy. The builder itself carried the same bug and was fixed; this document was not updated with it, so a DSP resolving our venuetype ids against OpenOOH 1.0 would have mapped them against the wrong version.
publisherobject
domainstring
keywordsstring

DemandPartners

Canonical INT-PK identity table for demand-side partners (DSPs/SSPs that Trillboards routes ad requests to). Wave 2 of pristine-state refactor. Replaces partner_key TEXT joins across the billing path.

PropertyTypeRequiredDescription
demand_partner_idstring, nullabledemand_partner_id INT is the canonical FK going forward; partner_key TEXT is kept as the wire-format alternate-key FOREVER (external partner-API auth + admin UI rely on it). Never propose dropping ...
partner_keystringyes
public_aliasstringyespublic_alias UNIQUE: this is the obfuscated external alias partner-API consumers see. partnerAlias.js will read from this table after Wave 2 cutover.
display_namestringyes
partner_typestringyes
archivedbooleanyes
created_atstringyes
updated_atstringyes

Device

PropertyTypeRequiredDescription
devicetypeinteger — one of 88 = Digital Out of Home (DOOH) per OpenRTB 2.6
uastring
makestring
modelstring
osstring
osvstring
connectiontypeinteger
winteger
hinteger
ifastringOS-sanctioned resettable advertising ID in the clear; omitted when unavailable or limited
ifa_typestring — one of aaid, rida, afai, idfa, tifa, msai, dpid, ppid, … (10 total)Legacy compatibility copy; canonical DSP-compatible placement is device.ext.ifa_type
extobject
geoobject
eidsarray of objectExtended device identifiers (IAB recommended for DOOH)

EarnerScreens

User-owned ad screens. Each row is a logical screen that can display ads. Links user to device. PG primary with Mongo legacy mirror.

PropertyTypeRequiredDescription
taxonomy_spec_versionstring, nullable
taxonomy_migrated_atstring, nullable
auction_modestring, nullable
auction_typestring, nullable
auction_enabled_atstring, nullable
auction_cohortstring, nullable
sync_is_masterboolean, nullable
sync_master_screen_idstring, nullable
sync_enabledboolean, nullable
sync_last_sync_atstring, nullable
sync_group_namestring, nullable
registration_sourcestring, nullable
last_offline_transition_atstring, nullable
is_standbybooleanyes
blocked_iab_categoriesarray of string
blocked_advertisersarray of string
pref_allow_tobaccoboolean, nullable
pref_allow_religiousboolean, nullable
pref_auto_approve_known_brandsboolean, nullable
pref_blocked_subjectsarray of string
pref_allowed_subjectsarray of string
pref_blocked_keywordsarray of string
pref_allowed_keywordsarray of string
geocode_sourcestring, nullable
venue_parentstring, nullable
venue_childstring, nullable
venue_grandchildstring, nullable
environment_typestring, nullable
placement_typestring, nullable
venue_statestring, nullable
venue_citystring, nullable
display_modestring, nullable
ad_interval_secondsinteger, nullable
sound_enabledboolean, nullable
advertisement_sizingstring, nullable
avg_dwell_time_secondsinteger, nullable
peak_hoursarray of string
delivery_modestringyes
loop_plan_idinteger, nullable
ntp_sync_requiredbooleanyes
venue_classification_sourcestring, nullableenrichment_status: PG GENERATED from (venue_classification_source, enrichment_failed_at); a real classification DOMINATES a stale failure stamp (success wins). Never written directly. Values: pendi...
device_platform_overridestring, nullable
hb_vast_tag_urlstring, nullable
hb_min_interval_secondsinteger, nullable
hb_last_sync_atstring, nullable
waterfall_partnersarray of stringyeswaterfall_partners is the ONLY pin store (order + whitelist; screen_partner_settings was never built). Serving reads it only with a screen_header_bidding_config row and ignores it once waterfall_op...
waterfall_total_timeout_msinteger, nullable
waterfall_optimized_atstring, nullable
programmatic_enabledbooleanyes
prog_currencystringyes
preferred_deal_idsarray of stringyes
last_programmatic_sync_atstring, nullable
mediation_priorityinteger, nullable
hive_stack_screen_idstring, nullable
hive_stack_site_idstring, nullable
hive_stack_unit_idstring, nullable
hive_stack_unit_uuidstring, nullable
hive_stack_synced_atstring, nullable
hive_stack_sync_statusstring, nullable
taggify_screen_idstring, nullable
gam_ad_unit_idstring, nullable
gam_ad_unit_codestring, nullable
gam_synced_atstring, nullable
gam_sync_statusstring, nullable
branding_overlay_enabledbooleanyes
branding_overlay_logo_urlstringyes
branding_overlay_logo_transformed_urlstringyes
branding_overlay_positionstringyes
branding_overlay_size_rationumberyesNUMERIC(5,4).
branding_overlay_padding_rationumberyesNUMERIC(5,4).
branding_overlay_opacitynumberyesNUMERIC(5,4).
branding_overlay_hide_on_adsbooleanyes
regionstringyes
physical_size_set_bystring, nullable
physical_size_set_atstring, nullable
offline_alert_sent_atstring, nullable
back_online_alert_sent_atstring, nullable
enrichment_failed_atstring, nullable
operating_hoursobject, nullable
slot_duration_secondsinteger, nullable
state_iso_3166_2string, nullable
geocoding_raw_responseobject, nullable
geocoded_atstring, nullable
photo_flaggedbooleanyes
photo_flagged_atstring, nullable
photo_flagged_by_mongo_idstring, nullable
photo_flag_reasonstring, nullable
photo_flag_notesstring, nullable
photo_notification_sent_atstring, nullable
photo_notification_countintegeryes
photo_quality_sent_atstring, nullable
l_bar_positionstring, nullable
block_group_geoidstring, nullable
dma_codestring, nullable
dma_namestring, nullable
place_namestring, nullable
neighborhoodstring, nullable
branding_overlay_placementstringyes
archetype_photo_urlstring, nullable
archetype_photo_keystring, nullable
archetype_photo_synced_atstring, nullable
offline_push_alert_sent_atstring, nullable
is_demo_databooleanyes
deleted_atstring, nullabledeleted_at IS NULL required — soft-delete nulls earnerscreen_device_id for partial unique index
partner_mongo_idstring, nullable
photosobject, nullable
photo_review_statusstring, nullable
venue_categorystring, nullable
venue_subcategorystring, nullable
venue_child_idstring, nullable
places_ratingnumber, nullable
places_review_countinteger, nullable
commercial_value_scorenumber, nullable
foot_traffic_multipliernumber, nullable
floor_price_cpmnumber, nullableNUMERIC(12,6).
distributor_idinteger, nullable
billing_modestringyes
ads_disabled_reasonsarray of stringyes
cms_payment_statusstringyes
ssp_enabledboolean, nullable
gam_ad_unit_pathstring, nullable
l_bar_ads_enabledboolean, nullable
width_inchesnumber, nullablePhysical width_inches/height_inches/diagonal_inches are inches. Pixels live on earner_screen_devices; the raw screen has no resolution_width/resolution_height columns.
height_inchesnumber, nullable
diagonal_inchesnumber, nullable
dynamic_floor_pricingboolean, nullable
prog_allocation_pctnumber, nullable
hb_providerstring, nullable
hb_timeout_msinteger, nullable
hb_enabledboolean, nullable
hb_allocationnumber, nullable
hb_request_modestring, nullable
hb_force_requestboolean, nullable
pref_blocked_categoriesarray of string
pref_allowed_categoriesarray of string
content_filtering_enabledboolean, nullable
pref_levelstring, nullable
pref_max_age_ratingstring, nullable
mobile_distance_threshold_minteger, nullable
mobile_update_interval_sinteger, nullable
mobile_vehicle_typestring, nullable
latitudenumber, nullable
longitudenumber, nullable
brand_substitution_modestringyes
brand_substitution_consent_atstring, nullable
brand_substitution_consent_bystring, nullable
serving_tenant_idinteger, nullable
enrichment_attemptsintegeryes
last_enrichment_attempt_atstring, nullable
media_capabilitystring — one of image_video, image_only, video_only
screen_placementstring, nullable

EventExt

Large-event proximity for the screen. The whole event sub-namespace is present ONLY when a nearby event was detected — its absence means "no nearby event", so nearby is always true when the object exists.

PropertyTypeRequiredDescription
nearbybooleanAlways true when this object is present.
countintegerNumber of nearby events detected
max_capacityintegerAttendee capacity of the largest nearby event
categorystringDominant category across the nearby events
audience_spikebooleanWhether an audience spike is expected from these events

FootTrafficExt

Real-time venue foot traffic metrics derived from FEIN audience sensing. Higher traffic = more impressions = higher value for advertisers.

PropertyTypeRequiredDescription
current_audienceintegerCurrent number of people detected (face count, rounded)
estimated_occupancyintegerEstimated total venue occupancy (extrapolated)
avg_dwell_secondsintegerAverage dwell time in seconds
traffic_tierstring — one of very_low, low, medium, high, very_highTraffic classification for easy targeting: - very_high: >= 50 people - high: 20-49 people - medium: 8-19 people - low: 3-7 people - very_low: < 3 people
estimated_hourly_impressionsintegerProjected impressions per hour based on face turnover rate

{
  "current_audience": 25,
  "estimated_occupancy": 50,
  "avg_dwell_seconds": 6,
  "traffic_tier": "very_high",
  "estimated_hourly_impressions": 15000
}

IABSegmentReference

Reference table of IAB Audience Taxonomy 1.1 segment IDs used by Trillboards.

Income Segments

IDName
1001High Income
1002Upper-Middle Income
1003Middle Income
1004Lower-Middle Income
1005Low Income

Lifestyle Segments

IDName
2001Business Professional
2002Student
2003Fitness Enthusiast
2004Luxury Shopper
2005Tech Savvy
2006Outdoor Active
2007Foodie
2008Health Conscious
2009Parent
2010Commuter
2011Tourist
2012Nightlife
2013Pet Owner
2014Gamer
2015Reader
2016Eco-Conscious
2017Fashion Forward
2018DIY/Home Improvement
2019Music Lover
2020Sports Fan

Purchase Intent Segments

IDName
3001High Purchase Intent
3002Medium Purchase Intent
3003Low Purchase Intent

Type: object

Impression

PropertyTypeRequiredDescription
idstring
tagidstringScreen MongoDB ID
bidfloornumberFloor price in CPM
bidfloorcurstring
secureinteger
dtintegerEstimated fulfillment timestamp (epoch seconds)
qtyobjectDOOH impression quantity/multiplier (OpenRTB 2.6)
bannerobject
videoobject

IntentExt

Purchase intent signals derived from ambient audio classification. YAMNet TFLite classifies audio SCENES (not speech content) on-device. Combined with visual shopping signals (bag detection) and demographic context to compute a composite intent score.

Higher intent_score = audience is more likely to make a purchase. DSPs can bid higher when purchase_stage is READY_TO_BUY or COMPARING.

PropertyTypeRequiredDescription
scorenumberComposite purchase intent score (0-1). Weighted combination of verbal intent, brand mentions, price inquiry, shopping activity, bag detection, income match, emotion, and engagement.
purchase_stagestring — one of READY_TO_BUY, COMPARING, CONSIDERING, BROWSING, NONEClassified purchase funnel stage based on behavioral signals. - READY_TO_BUY: High intent + brand mentions + price inquiry (score >= 0.7) - COMPARING: Active comparison shopping (score 0.5-0.7) - CONSIDERING: Interest shown but no purchase signals (score 0.3-0.5) - BROWSING: Casual browsing, low intent (score 0.1-0.3) - NONE: No purchase intent detected (score < 0.1)
categoriesarray of objectDetected product/service interest categories
brand_mentionsbooleanWhether brand names were detected in ambient audio
brand_countintegerNumber of distinct brand mentions detected
audience_sizeintegerCurrent audience size (face count) when intent was measured
should_triggerbooleanWhether intent score is high enough to trigger premium ad swap

OpenrtbRevenueScreenHourly

Revenue per screen per hour. Aggregates gross revenue from completed impressions. Refreshed from CH via clickhouseRollupSource. PG only.

PropertyTypeRequiredDescription
hour_bucketstringyes
screen_mongo_idstringyes
impressionsintegeryes
priced_impressionsintegeryes
estimated_impressionsintegeryes
actual_gross_revenuenumberyes
estimated_gross_revenuenumberyes
gross_revenuenumberyes
updated_atstringyes

PartnerReconciliationReports

Partner-reported impression and revenue counts for reconciliation against deduped completed_impressions. Ingested from VidVerto SSP API and Adipolo API / JustBaat CSV reports. PG only.

PropertyTypeRequiredDescription
their_requestsinteger, nullable
our_requestsinteger, nullable
request_variancenumber, nullableNUMERIC(10,4).
demand_partner_idinteger, nullableWave 2 B added demand_partner_id INT + variant_id INT FKs. Legacy partner_key TEXT kept as wire-format alternate-key. Backfill via follow-up Wave 2 B-backfill PR.
variant_idinteger, nullable
idinteger, nullableVidVerto synced daily via vidvertoRevenueSync before programmatic earnings aggregation.
provider_namestringyes
report_datestringyes
report_typestring — one of partner_api, manual_upload, email_extract, dashboard_snapshotyes
their_impressionsinteger, nullable
their_revenuenumber, nullableNUMERIC(14,6).
their_ecpmnumber, nullableNUMERIC(10,4).
their_fill_ratenumber, nullableNUMERIC(6,4).
our_impressionsinteger, nullable
our_revenuenumber, nullableNUMERIC(14,6).
our_ecpmnumber, nullableNUMERIC(10,4).
impression_variancenumber, nullableNUMERIC(8,4).
revenue_variancenumber, nullableNUMERIC(8,4).
statusstring — one of pending, matched, flagged, disputed, resolved, acceptedyes
resolution_notesstring, nullable
adjustment_idinteger, nullable
raw_dataobject, nullableAdipolo publisher revenue requires a completed vast_requests lifecycle plus latest screens_live source='owned'. ID shape/event alone is insufficient; shared, external, and unjoined bundles are excl...
imported_bystring, nullable
reviewed_bystring, nullable
reviewed_atstring, nullable
created_atstringyes
updated_atstringyes
applied_report_hashstring, nullableapplied_report_hash/applied_at (mig 449) gate the hourly pricing re-apply: syncs skip the CI re-stamp + PED rebuild when the applied tuple is unchanged. Written ONLY by partnerPricingApplyGate.reco...
applied_atstring, nullable

PartnerVariants

Canonical INT-PK identity for partner variants (e.g. adipolo_lower_floor_tablet). Wave 2 of pristine-state refactor. variant_name TEXT remains as the wire-format alternate-key indefinitely.

PropertyTypeRequiredDescription
variant_idstring, nullablefeeds_into lists tables that will gain a nullable variant_id INT FK in Wave 2 Stream B. Each is a separate PR — this PR mints the dimension only.
demand_partner_idintegeryesBackfill is 1:N from demand_partner_config.variant_names[]. Rows with NULL demand_partner_id at apply time are silently skipped — deploy-controller previous-tick guard ensures Wave 2 A1 has populat...
variant_namestringyesvariant_name TEXT is the wire-format alternate-key (kept forever) — internal logs and partner integrations rely on it. Never propose dropping variant_name.
public_aliasstringyespublic_alias is the obfuscation alias for partner-API responses (matches partnerAlias.encodeAlias pattern: 'var_' || sha256(variant_name)[0..5]).
display_namestring, nullablevast_tag_variants JSONB on demand_partner_config still co-exists during transition. Backfill UPDATE pulls display_name from the JSONB if present (no-op today; forward-compatible).
archivedbooleanyes
created_atstringyes
updated_atstringyes
daily_impression_capinteger, nullable
daily_request_capinteger, nullable
daily_budget_capnumber, nullableNUMERIC(10,2).
request_pressure_enabledboolean, nullablerequest_pressure_enabled=false fails open for pressure shaping only. It must not be treated as demand-source enablement.
request_pressure_base_interval_secondsinteger, nullable
request_pressure_probe_interval_secondsinteger, nullable
request_pressure_defer_secondsinteger, nullable
request_pressure_probe_modulointeger, nullable
request_pressure_probe_target_per_minutenumber, nullableNUMERIC(10,4).
request_pressure_min_pair_requestsinteger, nullable
request_pressure_min_source_requestsinteger, nullable
request_pressure_completion_rate_floornumber, nullableNUMERIC(12,8).
request_pressure_confidence_levelnumber, nullableNUMERIC(6,3).
request_pressure_max_multiplierinteger, nullable

PartnerZoneCpmDaily

Per-zone per-day CPM rates from partner APIs. Used for revenue estimation and settled partner-truth allocation when partner_reconciliation_reports does not provide a newer manual/API row. PG only.

PropertyTypeRequiredDescription
demand_partner_idinteger, nullableWave 2 B added demand_partner_id INT + variant_id INT FKs. Legacy partner_key TEXT kept as wire-format alternate-key. Backfill via follow-up Wave 2 B-backfill PR.
variant_idinteger, nullable
idstring, nullable
partner_keystringyes
zone_idstringyes
zone_labelstring, nullable
period_datestringyes
ecpmnumberyesNUMERIC(10,4).
gross_revenuenumber, nullableNUMERIC(14,6).
impressionsinteger, nullable
requestsinteger, nullable
fill_ratenumber, nullableNUMERIC(6,4).
sourcestringyesDaily earnings aggregation may use these rows to settle gross revenue, but completed_impressions remains the event-count source for programmatic_earnings_daily.impressions_count.
fetched_atstringyes
created_atstringyes
updated_atstringyes

Regs

PropertyTypeRequiredDescription
coppainteger
gdprintegerSet to 0 by the Trillboards request builder. On demand rails with wire hygiene enabled, the field carries the value from the authenticated publisher or device privacy context and is omitted when that context has none.

Segment

PropertyTypeRequiredDescription
idstringSegment identifier (IAB taxonomy ID or seller-defined)
namestringHuman-readable segment name
valuestring

SellerDefinedSegmentReference

Seller-defined context segments in the trillboards-seller-defined data object. These are included in user.data[] with ext.segtax omitted (seller-defined taxonomy).

Venue Segments (trb_vn_*)

IDNameMatches
trb_vn_001venue:fitness_gymgym, fitness, workout, crossfit
trb_vn_002venue:restaurant_casualcasual restaurant, diner
trb_vn_003venue:restaurant_quick_serviceQSR, fast food, takeout
trb_vn_004venue:bar_nightlifebar, nightlife, club, pub, lounge
trb_vn_005venue:salon_beautysalon, beauty, spa
trb_vn_006venue:barber_shopbarber
trb_vn_007venue:retail_generalretail, shopping, mall
trb_vn_008venue:retail_convenienceconvenience, gas station
trb_vn_009venue:office_lobbyoffice, cowork, business
trb_vn_010venue:healthcare_waiting_roomclinic, medical, hospital, pharmacy
trb_vn_011venue:education_campuscampus, college, university, school
trb_vn_012venue:hotel_hospitalityhotel, hospitality, resort
trb_vn_013venue:transit_hubtransit, station, airport, terminal
trb_vn_014venue:entertainmentcinema, theater, arcade, event
trb_vn_015venue:residential_commonresidential, apartment, condo, lobby

Geo Segments (trb_geo_*)

IDName
trb_geo_001geo:country_us
trb_geo_002geo:state_ca
trb_geo_003geo:state_ny
trb_geo_004geo:state_tx
trb_geo_005geo:city_tier_1

Traffic Tier Segments (trb_trf_*)

IDNameThreshold
trb_trf_001traffic:very_low< 3 people
trb_trf_002traffic:low3-7 people
trb_trf_003traffic:medium8-19 people
trb_trf_004traffic:high20-49 people
trb_trf_005traffic:very_high>= 50 people

Dwell Time Segments (trb_dwl_*)

IDNameThreshold
trb_dwl_001dwell:very_short< 3 seconds
trb_dwl_002dwell:short3-7 seconds
trb_dwl_003dwell:medium7-15 seconds
trb_dwl_004dwell:long> 15 seconds

Daypart Segments (trb_dpt_*)

IDNameHours (UTC)
trb_dpt_001daypart:morning05:00-10:59
trb_dpt_002daypart:midday11:00-13:59
trb_dpt_003daypart:afternoon14:00-17:59
trb_dpt_004daypart:evening18:00-22:59
trb_dpt_005daypart:late_night23:00-04:59

Quality Flags (trb_qly_*)

IDNameMeaning
trb_qly_001quality:geo_verifiedScreen has GPS coordinates
trb_qly_002quality:edge_sensed_audienceReal-time FEIN audience data present
trb_qly_003quality:floor_definedPublisher floor price is set

Type: object

Source

PropertyTypeRequiredDescription
fdinteger1 = exchange is final decision maker
tidstringTransaction/request ID
schainobjectSupply chain transparency

TrbNamespace

Trillboards extension sub-namespaces. Every sub-namespace is OPTIONAL and is omitted entirely when the underlying signal is unavailable for that screen — treat an absent key as "no signal", never as a zero.

This object is pinned to the request builder by tests/unit/openrtbExtNamespaceSpecParity.test.js, which derives the emitted key set from the source and fails on drift in either direction.

PropertyTypeRequiredDescription
vasVASExt
intentIntentExt
weatherWeatherExt
foot_trafficFootTrafficExt
venueVenueExt
eventEventExt

TrillboardsAudienceExt

Real-time audience intelligence from FEIN edge AI sensors. Updated every 10-30 seconds. These signals are MEASURED, not estimated. Unlike CTV viewability which uses probabilistic models, Trillboards uses on-device computer vision (ML Kit) and audio classification (YAMNet TFLite) to provide deterministic audience data.

PropertyTypeRequiredDescription
attention_scorenumberFraction of detected faces actively looking at the screen. 0.0 = nobody looking, 1.0 = everyone looking. Measured via gaze detection, NOT self-reported or probabilistic.
audience_countnumberAverage number of faces detected during current measurement window. Parse audience_count, not live_face_count. A previous revision of this spec documented this field as live_face_count and stated that audience_count "was never actually emitted by the server". That was exactly backwards, and it was a confusion of two different surfaces: - This surface — the outbound bid request's ext.trillboards — has always emitted audience_count. - The inventory discovery response (GET /openrtb/v2/adslots) emits live_face_count inside its fein object. Both names are live; they belong to different documents. live_face_count never appears in a bid request.
crowd_densityintegerPeak face count observed in current window (max concurrent viewers)
ad_receptivitynumberAudio-derived venue receptivity score. Quiet/focused environments score higher. Based on YAMNet ambient sound classification.
emotional_engagementnumberComposite emotional engagement score from facial expression analysis. Higher = more engaged (positive or negative reaction to content). Computed from each detected person's facial expression, classified on the device.
moodstring — one of happy, neutral, focused, calm, energetic, social, surprised, sadDominant venue emotional state derived from facial expression analysis. Parse mood, not dominant_emotion. Same surface confusion as audience_count above: the bid request emits mood; the GET /openrtb/v2/adslots discovery response emits dominant_emotion.
estimated_occupancyintegerEstimated venue occupancy (extrapolated from visible faces + venue capacity)
avg_dwell_msnumberAverage time (milliseconds) a face stays in the camera's field of view
group_compositionobjectAudience composition breakdown by demographic bucket. Derived from each detected person's estimated age range and gender.
screen_engagementstringCategorical engagement label passed through from the edge reading (e.g. active), NOT a score. Corrected 2026-09-01. This declared type: number with minimum: 0, maximum: 1 and example: 0.65, but _buildTrillboardsExt assigns audience.screenEngagement unchanged and that value is a string everywhere it is produced. A bidder doing arithmetic on this field was getting NaN. The combined 0-1 metrics are emotional_engagement and ad_receptivity.
audience_reactionstring — one of positive, neutral, negative, mixedDominant audience reaction to current content
signals_age_msintegerMilliseconds since last FEIN measurement update. Lower = fresher signals. Typical: 10,000-30,000ms. If > 120,000ms, signals may be stale (screen offline or camera occluded).
reliability_scorenumberScreen reliability score from unified telemetry. Factors: uptime, heartbeat regularity, GPS accuracy, FEIN measurement frequency.
audience_qualitynumberAudience data quality score. High = rich FEIN signals with high confidence. Low = limited or stale audience data.
screen_quality_compositenumberComposite quality score combining reliability + audience quality + geo accuracy
speech_contextsarray of stringShopping contexts inferred from on-device speech classification. The bid request carries the context labels; Trillboards stores the speech transcripts they come from. Omitted entirely when no context was inferred.
purchase_journey_stagestringWhere the observed audience sits in a purchase journey, derived from speech context. Omitted when no stage was inferred.
purchase_journey_urgencystringUrgency signal accompanying purchase_journey_stage. Omitted when no stage was inferred.
canonical_brand_matchesarray of stringDe-duplicated canonical brand names matched from speech evidence. Presence of a competitor brand is a conquesting opportunity. Omitted when no brand was matched.
signal_derivedobjectCamera-less derived audience signals, carried alongside the IAB and Trillboards segment sets. Present only when derived signals exist for the screen AND the request is not a clean curated-wire request.
agent_endpointstringAI-agent discovery: the Trillboards MCP endpoint, so a DSP's agent can negotiate directly from the bid stream. Constant for all requests.
adcp_discoverystringAI-agent discovery: the AdCP adagents.json document. Constant for all requests.

{
  "attention_score": 0.87,
  "audience_count": 8,
  "crowd_density": 12,
  "ad_receptivity": 0.75,
  "emotional_engagement": 0.82,
  "mood": "happy",
  "estimated_occupancy": 25,
  "avg_dwell_ms": 4500,
  "group_composition": {
    "solo": 3
  },
  "screen_engagement": "active",
  "audience_reaction": "positive",
  "signals_age_ms": 12480
}

User

User object carrying the screen's audience segments. The trillboards-audience segments are read from the per-person records the screen keeps for the people its camera detects. Trillboards recognises the same person across screens and days and links people to device keys and mobile advertising IDs.

PropertyTypeRequiredDescription
dataarray of UserData

UserData

IAB Audience Taxonomy 1.1 segments and seller-defined context segments. Three data sources may be present in user.data[]:

  1. trillboards-audience: Real-time audience segments from FEIN edge AI
  2. trillboards-census: US Census ACS neighborhood demographics
  3. trillboards-seller-defined: Seller-defined context segments (venue, traffic, dwell, daypart)
PropertyTypeRequiredDescription
idstring — one of trillboards-audience, trillboards-census, trillboards-seller-definedData provider identifier
namestringHuman-readable data source name
segmentarray of Segment
extobject

VASExt

Verified Attention Seconds — historical attention quality metrics for this screen. Based on 7-day rolling data from the attention_ledger.

VAS = face_count attention_score dwell_seconds. It captures the TOTAL attention delivered, not just whether someone was present. A screen with 3 attentive viewers for 10 seconds scores higher than 10 distracted viewers for 1 second.

PropertyTypeRequiredDescription
pricing_modelstring — one of vasAlways "vas" — indicates attention-based pricing is available
predicted_vasnumberPredicted VAS for the next impression based on historical patterns
vas_7dnumberAverage VAS (Viewable Attention Score) over the past 7 days. (Field renamed 2026-05 from historical_vas_avg to align with the buyer-facing field name on /adslots — partners migrating from a stale spec should rename their parser key.)
median_vasnumberMedian VAS (more robust to outliers than mean)
p90_vasnumber90th percentile VAS — the quality floor for top 10% of measurements
vas_floornumberMinimum VAS threshold for quality-gated pricing
vas_measurements_7dintegerNumber of VAS measurements in the past 7 days (data density)
avg_face_countnumberAverage face count across measurements
avg_attention_scorenumberAverage attention score across measurements
last_measurementstringTimestamp of most recent VAS measurement

VenueExt

Venue quality and neighborhood context for the screen's location.

Every field is omitted unless it carries positive value — a zero or unknown is dropped rather than broadcast, because a zero on the bid stream reads as "worthless" and suppresses bids. An absent field means "not known", not "scored zero".

PropertyTypeRequiredDescription
price_levelintegerVenue price tier (0 = cheapest, 4 = most expensive)
ratingnumberVenue rating on a 5-point scale
quality_scorenumberComposite venue quality score. Omitted when not positive.
neighborhood_classstringNeighborhood classification for the surrounding area. Omitted when unknown (the literal unknown is never sent).
amenity_densitynumberDensity of nearby amenities (retail, dining, transit) around the screen. Omitted when not positive.

WeatherExt

Contextual weather data for the screen's location. Cached in Redis with 60-minute TTL from WeatherAPI.com. DSPs use weather for contextual targeting (e.g., ice cream ads when hot, umbrella ads when raining).

PropertyTypeRequiredDescription
temp_fnumberCurrent temperature in Fahrenheit
feels_like_fnumberFeels-like temperature accounting for humidity and wind chill
humiditynumberRelative humidity percentage (0-100)
conditionstringWeather condition description
uv_indexnumberUV index (0-11+)
wind_mphnumberWind speed in miles per hour
is_rainingbooleanWhether it is currently raining at the screen location
temp_segmentstring — one of hot, warm, cool, coldTemperature classification for easy targeting: - hot: >= 85F - warm: 65-84F - cool: 45-64F - cold: < 45F

{
  "temp_f": 85,
  "feels_like_f": 88,
  "humidity": 75,
  "condition": "Partly cloudy",
  "uv_index": 8,
  "wind_mph": 12,
  "is_raining": false,
  "temp_segment": "hot"
}