Guides

bid.adm vs nurl: how the winning ad gets delivered in OpenRTB

When a bid wins, the exchange needs the actual ad and a way to count the impression. OpenRTB gives a bidder two ways to hand over the creative and three notice URLs to track what happens next. Getting the choice between them right is the difference between a fast render and an extra round trip, or a missed impression count.

Two ways to deliver the markup

  • adm (inline). The bidder includes the ad markup directly in the bid response. If the bid wins, the exchange already has the creative and can render it immediately, with no extra call back to the bidder.
  • nurl (win notice). The bidder omits the markup and gives a win notice URL instead. If the bid wins, the exchange calls nurl, and the bidder can return the markup in that response. It defers creative generation until the impression is actually won.

The spec settles the ambiguity: if markup is present in both, admsupersedes the win notice. So you send one or the other, not both expecting the nurl to win.

The tradeoff

Inline adm is one fewer round trip: the markup travels with the bid, so a win renders without waiting on the bidder again. The cost is that the bidder generates creative for every bid, including the ones that lose. nurl inverts that: no wasted markup generation, but a win incurs a second call back to the bidder before the ad can render, adding latency at the worst moment. Most display goes inline; deferred markup is chosen when generation is expensive or must be personalized at win time.

The three notice URLs

Beyond delivering markup, the bid response carries up to three tracking URLs the exchange fires at different moments:

  • nurl: called on a win. A win is not the same as a rendered, viewed, or billable ad; it just means this bid was selected.
  • burl: called when the win becomes billable under the exchange's policy, typically on delivery or viewability. This, not the win, is what a careful bidder counts as spend.
  • lurl: called on a loss, optionally with a loss reason code. Exchange policy may withhold it or strip the clearing price from it.

The distinction between win and billable is the one bidders most often collapse. Pricing algorithms should learn from nurl; actual spend should follow burl. See the bid response reference for the full object.

mtype: telling the exchange what the markup is

The mtype field on the bid states the creative type so the exchange can associate it with the right impression sub-object:

mtype (integer)
  1 = Banner
  2 = Video
  3 = Audio
  4 = Native

Setting mtype lets the exchange validate that a video bid is answering a video impression rather than trusting the markup to declare itself. A bid whose mtype contradicts the impression it answers is a bug worth catching.

Macros in the markup and notices

All of these fields, adm, nurl, burl, and lurl, may contain substitution macros that the exchange expands before firing. The most important is ${AUCTION_PRICE}, the clearing price. Because exchange policy can replace it with a zero-length string when it declines to disclose the price, markup and tracking that depend on it must tolerate an empty value rather than break.

What to check

  • Send adm or nurl, not both expecting nurl to win.
  • Set mtype to match the impression you are answering.
  • Count spend on burl, not nurl.
  • Handle an empty ${AUCTION_PRICE} expansion gracefully.

Validate a bid response, including its adm and notice fields, in the tester, or gate responses with the CLI.

Sources