Blog · Protocol

PMP vs preferred deal vs programmatic guaranteed is private_auction, at, and guar.

PMP vs preferred deal vs programmatic guaranteed is not three objects. OpenRTB gives you imp.pmp. The names are conventions on private_auction, Deal.at, and Deal.guar. Exchanges vary. The axes do not.

Read the three flags before you trust the IO

An open auction has no deal. private_auction 0 still accepts open bids beside any deals that are listed. private_auction 1 restricts bidding to the deals and their terms. A private auction, the closed invite, is that 1, with Deal.at of 1 or 2 so the price is still an auction, and guar 0 so the buyer is not obligated. The floor is competitive. The deals guide is the table. A request that says PMP in the subject line and leaves private_auction at 0 is still an open auction with a label.

A preferred deal is first look at a fixed price, and the buyer does not have to buy. That is Deal.at 3, meaning the bidfloor is the agreed price, and guar 0. Programmatic guaranteed is the committed buy: the same fixed price, and guar 1, which tells the bidder it must bid. Setting guar 1 on a preferred deal obligates a buyer who was only offered a look. Leaving it 0 on a guaranteed IO lets the bidder skip a commitment the seller already sold.

Deal.at overrides the request auction type for that deal. Request at defaults to 2, second price plus, when omitted. A deal with at 3 does not inherit that default. Loss code 103 is lost to a deal bid. It is not 102, which is a higher price. A bidder that treats every loss as price will raise the bid on a deal it was never in.

The id is the join, and the currency does not inherit

Deal.id is required and negotiated out of band. The seller puts it on the request. The buyer matches it to apply the terms. If the ids differ, the deal never triggers and the impression prices as open auction, with no error that says the name of the IO. A mismatched id is the usual reason a deal looks dead.

Deal.bidfloorcur does not inherit imp.bidfloorcur. Both default to USD when omitted. A euro floor on the impression plus a bare deal floor is a dollar deal. wseat and wadomain, when omitted, mean no seat restriction and no advertiser-domain restriction. When present, they are the only buyers allowed on that deal. Omission is not "everyone we usually trade with."

These encodings are conventions. An exchange can still use a different combination. Read the three flags on the request you were sent. Do not replace them with the words in the order. Validate the pmp block in the tester against the snapshot that exchange speaks. Spec JSON wants private_auction and guar as integers. true is the protobuf dialect.

A fixed price with the wrong obligation is a different product

Preferred and programmatic guaranteed both use Deal.at 3, so a dashboard that only shows fixed price cannot tell them apart. guar is the obligation. 0 means the buyer may pass. 1 means the bidder must bid. A trader who marks every fixed deal guaranteed will force bids on inventory the buyer only had a first look at. A trader who leaves guar off on a guaranteed IO will see the bidder no-bid a commitment that was already sold.

wseat limits which buyer seats may bid. wadomain limits advertiser domains. Omission means no restriction. A preferred deal offered to one seat still needs that seat in wseat if the exchange is using the field. An empty wseat is not one seat. private_auction 1 then means only the listed deals, so an open-auction bid you expected as a backstop will not be accepted.

When the deal id mismatches, nothing in the response says the IO name. The impression clears at the open auction, loss reasons look like price, and the deal report stays at zero. Compare Deal.id on the request to the id in the order before you debug floors. Then compare bidfloorcur. A 120 floor without JPY is 120 US dollars, on the deal and on the impression separately.

What to confirm before the deal goes live

  • Private auction: private_auction 1, at 1 or 2, guar 0.
  • Preferred deal: at 3, guar 0. The floor is the price. The buyer may pass.
  • Programmatic guaranteed: at 3, guar 1. The bidder is obligated.
  • Match Deal.id on both sides. A near miss falls through to the open auction.
  • Set bidfloorcur on the deal. A bare floor is USD.
  • Do not expect open bids when private_auction is 1.

The open auction is what you get when the flags do not match the IO

If private_auction is 0, open bids are still accepted beside the deals. A buyer who thought the package was a closed PMP will see other seats clearing it. If private_auction is 1 and the buyer is not on the deal, that buyer cannot fall back to the open price. Both outcomes look like a yield change. Both are the flag.

guar 1 without a real commitment makes the bidder spend on a look. guar 0 on a guaranteed buy makes the bidder skip a contract. at 3 without the currency makes the fixed price USD. Read the JSON the exchange sent, not the deal name in the email, and do not ship a fixture that was edited to match the IO after the builder already wrote different flags.

Further reading