Learning Track

OpenRTB

Decode bidstream contracts, annotate request fields, and catch malformed payloads before they become revenue leaks.

Intermediate track

What this page gives you before the bidstream details

This page is aimed at an intermediate reader: you know the broad programmatic flow already, and now you want to decode request fields, understand auction contracts, and spot malformed payloads faster.

What this page covers

  • Core OpenRTB 2.6 objects: imp, site, device, user, regs, source.
  • How consent, identity, and media fields affect demand eligibility.
  • Bid response anatomy and win-notice mechanics.

What is inside

  • Fully annotated bid request and bid response JSON examples.
  • Field reference table with types, allowed values, and failure impact.
  • Common no-bid and compliance failure patterns with fixes.

Best way to use it

  • Decode a real request while reading — not in isolation from logs.
  • Mark missing or suspicious fields and connect them to auction outcomes.
  • Build a "red flags" checklist you can apply to any SSP log export.

Why it matters

OpenRTB is the lingua franca between buyers (DSPs) and sellers (SSPs). Every field in a bid request is a signal that tells a DSP whether to bid, how much to bid, and under what constraints. Missing or malformed fields — a blank geo, missing consent string, wrong device type — cause no-bids that silently kill fill rate. TAMs who can read and annotate these requests diagnose issues in minutes instead of days.

How an OpenRTB auction works — in 6 steps

  1. Publisher triggers an ad request — the page or app fires a request to the SSP when an ad slot loads.
  2. SSP builds the bid request — assembles the OpenRTB JSON payload with imp, site/app, device, user, regs, source objects.
  3. SSP fans out to DSPs — sends the same payload (or per-DSP variations) to connected buyers within the tmax window (typically 100–300 ms).
  4. DSPs respond with bid responses — each responding DSP returns a seatbid with a price, creative markup (adm), and metadata.
  5. SSP runs the auction — compares all bids against the floor (bidfloor), applies any deal priority, selects the winner.
  6. Win notice and billing — SSP fires the winning DSP's nurl (win notice URL) with the clearing price substituted into the macro ${AUCTION_PRICE}.

Annotated bid request (OpenRTB 2.6)

A realistic example covering banner, site context, geo, identity, and consent. Each key section is explained below the payload.

JSON OpenRTB 2.6 — Bid Request
{
  "id": "7d9b6c3a-1f4e-4b8a-9c2d-0e5f8a1b7c3e",   // Unique auction ID — matches bid response id
  "at": 1,                                              // Auction type: 1 = first-price, 2 = second-price
  "tmax": 150,                                          // Timeout in ms — DSPs must respond within this
  "cur": ["USD"],

  "imp": [
    {
      "id": "1",
      "banner": {
        "w": 300, "h": 250,
        "api": [3, 5]                          // 3=MRAID 2.0, 5=ORMMA — supported APIs
      },
      "bidfloor": 1.50,                                 // Minimum CPM — bids below this are ignored
      "bidfloorcur": "USD",
      "secure": 1,                                      // 1 = HTTPS required for all creative assets
      "tagid": "ad-unit-leaderboard-home"               // Publisher-defined placement label
    }
  ],

  "site": {
    "id": "site-abc-001",
    "page": "https://example.com/article/adtech-101",
    "domain": "example.com",
    "cat": ["IAB12"],                                   // IAB content category — used for brand safety
    "publisher": {
      "id": "pub-456",
      "name": "Example Media"
    },
    "ref": "https://google.com/search?q=adtech"         // Referring URL — signals intent context
  },

  "device": {
    "ua": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
    "ip": "203.0.113.42",                              // Truncated or hashed in GDPR regions
    "geo": {
      "country": "USA",
      "region": "CA",
      "city": "Los Angeles",
      "lat": 34.0522, "lon": -118.2437,
      "type": 2                                         // 1=GPS, 2=IP-derived, 3=user-provided
    },
    "devicetype": 2,                                    // 1=PC, 2=Phone, 3=Tablet, 4=TV, 5=Game Console, 6=Watch
    "os": "Windows",
    "language": "en",
    "dnt": 0                                            // Do Not Track — 0=no restriction, 1=limit tracking
  },

  "user": {
    "id": "u-78901-hashed",                            // Publisher or SSP user ID (not exposed in GDPR scope)
    "buyeruid": "buyer-xyz-001",                       // DSP's own user ID synced via cookie sync
    "consent": "CPXxRfAPXxRfAAfKABENAfCIAP_AAH_AAAqIHItf...", // IAB TCF v2 consent string
    "ext": {
      "eids": [                                                  // Extended IDs — clean-room / cookieless identity
        {
          "source": "liveramp.com",
          "uids": [{ "id": "RampID-abcde12345", "atype": 3 }]
        },
        {
          "source": "uidapi.com",
          "uids": [{ "id": "TDID-00112233aabbcc", "atype": 1 }]
        }
      ]
    }
  },

  "regs": {
    "coppa": 0,                                         // 1 = COPPA applies — no behavioral targeting
    "ext": {
      "gdpr": 1,                                        // 1 = GDPR applies — consent string required
      "us_privacy": "1YNN"                             // CCPA string: 1=spec ver, Y=notice, N=opt-out, N=LSPA
    }
  },

  "source": {
    "tid": "7d9b6c3a-1f4e-4b8a-9c2d-0e5f8a1b7c3e",  // Must match bid request id for traceability
    "pchain": "publisher:pub-456,exchange:ex-001"       // Supply chain transparency (see ads.txt / sellers.json)
  }
}
Field completeness directly affects fill rate. DSPs filter on geo, consent, device type, and floor before evaluating creatives. A missing regs.ext.gdpr in a EU request causes most DSPs to drop the bid entirely to avoid compliance risk.

Key fields explained

  • imp[].bidfloor Minimum CPM (in bidfloorcur currency). Bids below this are silently dropped — the DSP sees no error. Floors set too high cause low fill; too low reduces revenue.
  • imp[].secure Must be 1 for HTTPS pages. If 0 or missing on a secure page, DSPs serving HTTPS-only creatives will no-bid even if they win the price check.
  • device.devicetype Controls which campaigns target this inventory. CTV campaigns require 3 (SmartTV) or 4 (SetTopBox). Wrong value routes mobile-only budgets to desktop — or vice versa.
  • device.geo.type Tells buyers how accurate the location is. GPS-derived (1) commands a premium; IP-derived (2) is standard; missing geo is a no-bid trigger for geo-targeted campaigns.
  • user.consent IAB TCF v2 consent string. Must be present when regs.ext.gdpr=1. An empty or malformed string causes GDPR-compliant DSPs to drop the bid. Use the IAB consent string decoder to verify purposes are set.
  • user.ext.eids Cookieless identity signals (RampID, UID2, etc.). DSPs with identity graphs match these to their own profiles — no eids = no match rate = lower CPM from identity-enabled buyers.
  • regs.ext.us_privacy CCPA string, format 1YNN. Position 2 = notice given, position 3 = opted out of sale. If position 3 is Y, many DSPs suppress retargeting.
  • source.pchain Supply chain identifier. Required by many DSPs to verify ads.txt/sellers.json compliance. Missing or mismatched pchain causes brand-safety blocks.
  • tmax Total timeout in ms from SSP sending to receiving DSP responses. DSPs use this to decide if they can run ML scoring in time. Values below 100 ms cause many adapters to no-bid without attempting.

Annotated bid response

The DSP's reply. The SSP selects the winning bid, fires the nurl win notice, and serves the adm creative markup.

JSON OpenRTB 2.6 — Bid Response
{
  "id": "7d9b6c3a-1f4e-4b8a-9c2d-0e5f8a1b7c3e",   // Must match bid request id exactly
  "cur": "USD",
  "seatbid": [
    {
      "seat": "dsp-seat-001",                       // Buyer seat ID registered with the SSP
      "bid": [
        {
          "id": "bid-00a1b2c3",                    // DSP-generated bid ID
          "impid": "1",                            // Must match imp[].id from the request
          "price": 2.85,                           // CPM in USD — compared against bidfloor (1.50)
          "adid": "creative-55",
          "adm": "<script src='https://cdn.dsp.example/ad.js'></script>", // Creative markup served to the page
          "adomain": ["advertiser.com"],           // Advertiser domain — used for brand safety and ads.txt checks
          "iurl": "https://cdn.dsp.example/preview.png", // Image preview URL for SSP review
          "cid": "campaign-99",
          "crid": "creative-55",                   // Creative ID — used to block specific creatives
          "cat": ["IAB12"],                        // Advertiser category — must not conflict with site.cat blocks
          "w": 300, "h": 250,
          "nurl": "https://pixel.dsp.example/win?p=${AUCTION_PRICE}&id=bid-00a1b2c3",
          // ↑ Win notice URL. SSP fires this on win, substitutes real clearing price into ${AUCTION_PRICE}
          "burl": "https://pixel.dsp.example/bill?p=${AUCTION_PRICE}",
          // ↑ Billing notice (OpenRTB 2.6+) — fires when impression is billable (viewable or rendered)
          "lurl": "https://pixel.dsp.example/loss?reason=${AUCTION_LOSS}"
          // ↑ Loss notice — SSP fires with loss reason code (e.g. 102=below floor, 100=bid timeout)
        }
      ]
    }
  ]
}
nurl vs burl: nurl fires on auction win (before rendering). burl fires only when the impression is billable. In first-price auctions, always confirm which one the DSP uses for billing reconciliation — using nurl for billing overstates delivery when impressions don't render.

OpenRTB object reference

Key objects, their required/optional status, and what breaks when they are missing.

Object / Field Type Required? What breaks if missing
imp[].bidfloor float Recommended No floor = DSPs may bid penny prices; yield drops
imp[].secure int (0/1) Required on HTTPS HTTPS-only DSPs no-bid; mixed content warnings
site.page string (URL) Strongly recommended Brand-safety scanning fails; many DSPs no-bid
device.ua string Recommended Device targeting breaks; fraud signals weaken
device.geo object Recommended Geo-targeted campaigns skip this impression entirely
device.devicetype int Recommended Device type targeting fails; CTV/mobile budgets miss
user.consent string (TCF) Required (GDPR) GDPR-compliant DSPs no-bid 100% in EU traffic
user.ext.eids array Optional Identity-based targeting fails; lower CPM from ID-enabled DSPs
regs.ext.gdpr int (0/1) Required (GDPR) Missing = ambiguity; most buyers treat unknown as regulated
regs.ext.us_privacy string Required (CCPA) CCPA-compliant DSPs may default to suppressing retargeting
source.pchain string Recommended Brand-safety DSPs block — cannot verify supply path

Common failure patterns

The most frequent reasons a bid request produces no bids — and how to diagnose them.

Missing or blank geo

Geo-targeted campaigns simply skip the impression. You'll see high bid request volume but low DSP bid rate for campaigns with geo restrictions.

▸ Check: is device.geo populated? Is geo.country set? If IP is hashed for privacy, is fallback geo available?

Missing consent string in GDPR traffic

When regs.ext.gdpr=1 but user.consent is absent, GDPR-compliant DSPs have no legal basis for behavioral targeting and must no-bid. A TCF string must encode at least purposes 1 (storage) and 3 (profiling) to enable most demand.

▸ Check: parse the consent string with the IAB TCF decoder. Confirm purposes 1, 3, 4 are granted.

Wrong devicetype for CTV

CTV inventory sent with devicetype=2 (phone) is invisible to CTV-specific campaigns. Samsung Ads and similar CTV DSPs filter on devicetype at the first pass.

▸ Check: CTV apps should send devicetype=3 (SmartTV) or devicetype=4 (SetTopBox). Confirm with the publisher's SDK configuration.

Bid below floor (102)

Floor set too aggressively for the audience or content tier. The SSP returns loss reason code 102 to the DSP. You may see this in the lurl firing with reason=102.

▸ Check: compare bidfloor against DSP bid distribution in your reporting. A floor above the 75th percentile of bids clears most demand.

Timeout (tmax too low)

tmax under 100 ms causes many DSPs to no-bid without even attempting ML scoring. Loss reason 100 (bid expired) or 0 (no response) in lurl indicates this.

▸ Check: raise tmax to at least 150 ms for web, 200 ms for CTV. Coordinate with DSP partners on their minimum bidder latency.

adomain / adcat mismatch

Bid wins the auction but the creative is blocked by the publisher's block list. The SSP fires the nurl but returns an error page or empty slot.

▸ Check: compare bid.adomain against site publisher block lists. A DSP may routinely submit from a different adomain than the apparent advertiser.

No-bid reason codes (NBR)

When a DSP wants to explain a no-bid, it returns a 204 with a nbr field. Not all DSPs populate this, but it is critical for diagnostics when they do.

CodeMeaningCommon cause
0Unknown errorDSP-side issue; contact their support team
1Technical errorMalformed JSON or missing required field
2Invalid requestOpenRTB version mismatch or unsupported extension
3Known web spider / botIVT detected by DSP — check traffic quality
5No inventory matchPublisher, domain, or category blocked by DSP
6No audience matchNo user ID match — cookieless or sync gap
7Below floorDSP bid lower than bidfloor — raise campaign CPM or lower floor
9User opt-out / blockedConsent string missing purposes or user opted out

Practice drills and outputs

Drill 1 — Annotate 20 bid requests

  • Export raw bid request logs from your SSP sandbox or test environment.
  • For each request: identify the top 5 revenue-relevant fields and their values.
  • Flag any field that is missing, null, or has a suspicious value (blank geo, empty consent, missing adslot).
  • Output: bid-request-annotations.csv with columns: field, value, risk level, notes.

Drill 2 — Consent string audit

  • Take 10 real consent strings from GDPR-region traffic.
  • Decode each using the IAB TCF decoder (available in the IAB Tech Lab GitHub).
  • List which purposes are granted vs denied. Note which DSPs require purposes 1+3+4 vs just 1.
  • Output: consent-audit.md with per-string purpose matrix.

Drill 3 — No-bid root cause analysis

  • Pull a set of bid requests with 0 bids from any connected DSP for one week.
  • Group by likely NBR code: floor, consent, geo, device, timeout.
  • Estimate the revenue impact of each failure category.
  • Output: nobid-rca.md with prioritized fix list.

References

  • IAB Tech Lab — OpenRTB 2.6 specification (iab.com/guidelines)
  • IAB TCF v2.2 — consent string format and purpose definitions
  • ads.txt / sellers.json — supply chain transparency specs
  • IAB OpenRTB loss reason codes (Appendix B of spec)

AdTech Toolkit

Enter any two values
to calculate the third

More tools coming soon