What is a bid request, and which fields should a buyer check?
Part of Supply path transparency

The short answer
A bid request is the message an exchange sends to bidders to offer one or more ad impressions for sale. In OpenRTB it carries the impression slots, the site or app, the device, the supply chain and any deals. Buyers read it to decide whether to bid and how much, and later to audit what they bought.
Key takeaways
- OpenRTB requires only two things in a bid request: an id and at least one imp object; everything else is recommended or optional.
- The site, publisher and source.schain objects are where a buyer matches the request to ads.txt and sellers.json.
- The imp object holds the slot size, the floor, its currency and any private marketplace deals offered on that impression.
- Every bid in the response points back to the request through the request id, the impid and, for deals, the dealid.
What is a bid request in programmatic advertising?
Definition
- Bid request
- A structured message, such as JSON under the OpenRTB protocol, in which an exchange or other supply source describes an ad opportunity and invites bidders to respond with an offer before a time limit runs out.
The OpenRTB 2.6 specification (opens in a new tab) from IAB Tech Lab says RTB transactions are initiated when an exchange or other supply source sends a bid request to a bidder. IAB Tech Lab's programmatic auction definitions (opens in a new tab), written for brand and agency leaders, call it an ad request: the information about the ad impression to be auctioned.
Very little is mandatory. Only Imp is technically required, and each Imp needs at least one of Banner, Video, Audio or Native to say what kind of ad the publisher will accept. Site, App and DOOH are highly recommended, but only one of them may appear in a request. So two requests for the same site can look very different: one exchange fills in the page URL and supply chain, another sends little more than a domain and a slot size.
What information does a bid request contain?
The easiest way to learn the format is to read one request from the outside in. The table below follows a fictional banner request for a racquet sports blog at courtside.example, a reserved documentation domain, in the order a reviewer would open each object. Field names and their meanings come from OpenRTB 2.6; the values are illustrative.
| Field | Sample value | What the specification says it means |
|---|---|---|
| id | a91f2c | ID of the bid request, assigned by the exchange, used to track the responses |
| at | 1 | Auction type: 1 is first price, 2 is second price plus; 2 is the default if omitted |
| imp[0].banner.format | 300 by 250 and 320 by 50 | The banner sizes permitted for this impression |
| imp[0].bidfloor and bidfloorcur | 1.20, USD | Minimum bid in CPM, and its currency, which defaults to USD |
| site.domain and site.page | courtside.example and an article URL | Domain of the site, and the URL of the page where the impression will be shown |
| site.publisher.id | 8841 | Exchange specific seller ID, matching a seller_id in the exchange's sellers.json |
| device.geo.region | GA | Region code; a two letter state code for the United States |
| source.schain | complete 1, two nodes | The links in the supply chain and whether the chain is complete |
| regs.coppa | 0 | Whether the request is subject to the FTC's COPPA rules, 0 is no and 1 is yes |
Which bid request fields identify the site and seller?
Three places name who is selling. site.domain and site.page say where the ad is meant to appear. site.publisher describes the entity that directly supplies inventory to the exchange and is paid by it, which the specification notes may be a publisher, an intermediary exchange or an ad network. Its id corresponds to a seller_id in the exchange's sellers.json. And source.schain lists every system and seller account in the flow of payment, each node carrying asi, the advertising system's domain, and sid, the seller account.
Those places line up with the public files. Under the ads.txt 1.1 specification (opens in a new tab) the publisher lists each authorized advertising system and account ID, and the sellers.json specification (opens in a new tab) says its seller_id is the same ID that appears in ads.txt and in the schain sid.
Match one logged request to the public files
- Take the domain from site.domain. Open that domain's ads.txt and find the lines for the exchange that sent the request.
- Take the seller ID from site.publisher.id. Confirm the same account ID appears on one of those ads.txt lines, and note whether the line says DIRECT or RESELLER.
- Look the ID up in the exchange's sellers.json. Read the seller_type: PUBLISHER, INTERMEDIARY or BOTH, and the name and domain if they are not confidential.
- Walk the schain nodes. Check that each asi and sid pair is a real account and that complete is 1; a complete chain starts with the owner of the site.
- Record any mismatch with the request id. A domain whose ads.txt does not list the seller, or a chain that does not start with the owner, goes to the exchange with that id attached.
What do the imp, device and pmp objects tell a buyer?
The Imp object is the item for sale. One request can carry several Imp objects, for example every ad position on a page, each with its own id so bids can name the one they want. Inside sit the formats, the floor, the private marketplace container and a Refresh object, in which a seller can declare how many times a slot has refreshed since the page loaded, a signal tied to the ad refresh questions planners already ask.
| Field | What it carries | Why a buyer reads it |
|---|---|---|
| imp.tagid | The specific placement or ad tag that started the auction | Ties delivery back to one slot when a site has many |
| imp.refresh.count | Times the slot refreshed since the last page load | Shows refreshed impressions apart from first views |
| imp.pmp.private_auction | 1 means bids are restricted to the listed deals | Tells the buyer whether open bids are allowed at all |
| imp.pmp.deals[].id and at | The deal ID, and an optional auction type override | at of 3 means the deal floor is the agreed price |
| device.devicetype and sua | General device type and structured user agent | Separates phone, desktop and connected TV traffic |
| device.geo.country | Country as an ISO 3166 alpha 3 code, such as USA or CAN | Confirms the impression sits inside the plan's market |
Under the Pmp object, private_auction set to 1 means only bids on the listed deals are accepted. Each Deal can carry its own bidfloor, a bidfloorcur that does not inherit from the impression, a wseat list of allowed seats, and guar set to 1 for a guaranteed deal the bidder must bid on. The deal ID guide covers how those IDs reach the buying platform.
How does a bid response answer a bid request?
The bid response is the bidder's reply, and every part of it points back to the request. Its id equals the request id. Each SeatBid names the buyer seat, the advertiser or agency the bid is for, and each Bid names its impid, a CPM price, the advertiser domain in adomain, a creative ID in crid and, for a deal, the dealid. A bidder that passes returns an empty HTTP 204 or a reason code in nbr.
The notices matter for audits. OpenRTB calls nurl the win notice, not necessarily a sign of a delivered, viewed or billable ad, and burl the billing notice, fired when the win becomes billable under the exchange's policy. The implementation notes (opens in a new tab) add that most exchanges bill on some form of delivery or rendering, not the auction win alone, so won bids and billed impressions can differ.
What should a buyer check in bid request logs?
A buyer working through a buying platform sees log level files, not raw bidstream traffic. Those files keep a subset of request fields next to each won impression. Ask the trading desk which fields the log keeps, then run this list on a sample of rows for every site on the plan.
Bid request log review for one site list
- Every logged domain is on the approved site list, with no unexpected subdomains or app bundles.
- Each seller ID in the log appears on the matching line of that domain's ads.txt.
- The sellers.json seller_type for each ID was recorded, and INTERMEDIARY accounts match a known reseller.
- Supply chains are complete, or incomplete ones are listed with the exchange that sent them.
- Deal IDs in the log match the deal sheet, and private_auction was 1 where the deal was meant to be private.
- Floors and currencies are read together, so a CAD floor is never compared with a USD bid.
What does a bid request review look like on a real plan?
Fictional example
A racquet sports retailer checks its logs in Georgia and the Carolinas
A fictional Atlanta retailer of tennis and pickleball equipment runs a display plan across 30 sports and local lifestyle sites in Georgia, North Carolina and South Carolina. After the first week, the planner asks the trading desk for 200 logged impressions with domain, seller ID, schain, deal ID and region.
Most rows match. A club news site's seller ID is DIRECT in its ads.txt and PUBLISHER in the exchange's sellers.json, so both sides agree. A pickleball blog shows a seller ID marked INTERMEDIARY that its ads.txt lists as RESELLER for a sales house, so the planner records the reseller path instead of removing the site.
Two problems go back to the desk with request ids attached: rows from a portal subdomain that is not on the list, and a few region values outside the three states. The desk tightens domain targeting and asks the exchange how it fills device.geo.
How does PlacementGraph prepare the site list a bid request is checked against?
A log review is only as useful as the list it is checked against, and that list exists before the first request.
Frequently asked questions
Can one bid request offer more than one impression?
Yes. The imp field is an array, so an exchange can offer every ad position on a page in one request, each with its own id, and bids name their slot through impid. When allimps is set to 1, the impressions offered are all of those available in that context, which supports roadblocks.
What does the test field in a bid request mean?
It marks test traffic. OpenRTB defines test as 0 for live mode and 1 for test mode, in which auctions are not billable. Exchanges and buying platforms use test requests while setting up an integration or a deal, and they should never count in delivery or log reviews.
How long does a bidder have to answer a bid request?
The tmax field sets the limit: the maximum time in milliseconds the exchange allows for bids to be received, including internet latency. Google's Authorized Buyers OpenRTB guide says the value is typically between 80 ms and 1500 ms. A late bid is a timeout and does not compete.
Does a bid request for an app look different from one for a website?
The structure is the same, but an app request carries an App object instead of a Site object, and a request must not contain more than one of Site, App or DOOH. The App object identifies the app through bundle, its store ID, and storeurl, and app sellers are authorized through app-ads.txt rather than ads.txt.
Sources
- OpenRTB 2.6 specification (opens in a new tab)IAB Tech Lab (GitHub)
- OpenRTB 2.6 implementation notes (opens in a new tab)IAB Tech Lab (GitHub)
- Programmatic Auction Definitions (opens in a new tab)IAB Tech Lab (GitHub)
- ads.txt 1.1 specification (opens in a new tab)IAB Tech Lab (GitHub)
- sellers.json specification (opens in a new tab)IAB Tech Lab (GitHub)
- OpenRTB Integration (Authorized Buyers real-time bidding) (opens in a new tab)Google for Developers
Researched and written by PlacementGraph Research. Read how we research, source and update these pages. Corrections: diana@placementgraph.com.