当 Google 向您的应用发送出价请求时,实时出价互动便会开始。本指南介绍了如何编写应用代码以处理出价请求。
解析请求
Google 会发送以 OpenRTB JSON 或 Protobuf 格式序列化的出价请求,并将其附加为 HTTP POST 请求的载荷。收到的格式取决于端点的配置。如需查看示例,请参阅出价请求示例。
您必须解析此请求才能接收序列化的 BidRequest
。如果您使用的是 Protobuf 格式,则必须从参考数据页面下载 openrtb.proto
和 openrtb-adx.proto
,并使用它们生成可用于解析 BidRequest
消息的库。例如,以下 C++ 代码会根据字符串中的 POST 载荷解析请求:
string post_payload = /* the payload from the POST request */; BidRequest bid_request; if (bid_request.ParseFromString(post_payload)) { // Process the request. }
获取 BidRequest
后,您可以将其作为对象进行处理,提取和解读所需的字段。例如,在 C++ 中,对 OpenRTB `BidRequest` 中的交易进行迭代可能如下所示:
for (const BidRequest::Imp::Pmp::Deal& deal : pmp.deals()) { DoSomething(deal.id(), deal.wseat()); }
结算 ID
当您的一个或多个
预定位配置定位到发布商的广告资源时,您就会收到出价请求。BidRequest.imp.ext.billing_id
将填充所有符合条件的买方的结算 ID 和相关的预定位配置。此外,对于交易广告资源,您可以使用 BidRequest.imp.pmp.deal.ext.billing_id
查找与相关买方关联的结算 ID。在出价时,只能指定出价请求中包含的买方的结算 ID。
如果出价请求中包含多个结算 ID,您必须使用 BidResponse.seatbid.bid.ext.billing_id
字段指定您打算将出价归因到的买方的结算 ID。
字典文件
出价请求使用字典文件中定义的标识符,这些标识符可在参考数据页面上找到。
出价方网址宏
您可以选择使用宏将 BidRequest
中的部分信息插入出价端点网址中。如果您使用一个或多个宏配置端点网址,那么如果出价请求中包含这些信息,系统会展开这些宏。例如,如果您想根据 BidRequest
中的信息执行负载均衡,这会非常有用。请与您的客户经理联系,请求针对新宏提供支持。
宏 | 说明 |
---|---|
%%GOOGLE_USER_ID%% |
已替换为 如果 Google 用户 ID 未知,系统会用空字符串进行替换,结果类似于 http://google.bidder.com/path?gid= |
%%HAS_MOBILE%% |
已替换为 |
%%HAS_VIDEO%% |
已替换为 |
%%HOSTED_MATCH_DATA%% |
已替换为基于 |
%%MOBILE_IS_APP%% |
已替换为 |
从交易网址中查找移动应用 ID
移动应用交易将报告如下网址:
mbappgewtimrzgyytanjyg4888888.com
使用以 32 为底数的解码器解码粗体显示的字符串部分 (gewtimrzgyytanjyg4888888
)。
您可以使用在线解码器,但必须将字母转换为大写,并将尾随 8
替换为 =
值。
因此,解码此值:
GEWTIMRZGYYTANJYG4======
1-429610587
429610587
是 iOS 应用 iFunny 的应用 ID。
再看下面一个示例。举报的网址是:
mbappgewtgmjug4ytmmrtgm888888.com
GEWTGMJUG4YTMMRTGM======
1-314716233
314716233
是 iOS 应用 TextNow 的应用 ID。
从交易网址中查找移动应用名称
下面是获取应用名称的示例。报告的网址如下所示:
mbappMFUXELTDN5WS42DZOBQWQLTJN4XHG3DJORUGK4Q888.com
MFUXELTDN5WS42DZOBQWQLTJN4XHG3DJORUGK4Q===
air.com.hypah.io.slither
公开出价字段
发送给参与公开出价的广告交易平台和广告联盟出价方的出价请求与参与标准实时出价的 Authorized Buyers 买方的出价请求类似。公开出价功能的客户将会收到少量额外的字段,并且部分现有字段可能有其他用途。这些情况包括:
OpenRTB | 详细信息 |
---|---|
BidRequest.imp.ext.dfp_ad_unit_code |
包含发布商的 Ad Manager 广告资源网代码,后跟广告单元层次结构,以正斜线分隔。 例如,其格式类似于 |
BidRequest.user.data.segment |
从发布商发送到广告交易平台出价方的重复键值对。 当 |
声明允许的供应商
提供调研、再营销和广告投放等服务的技术供应商可能会在买卖双方互动中发挥作用。只有 Google 已审核并批准参与 Authorized Buyers 互动的供应商才可以使用此 API。
如需了解 BidRequest
并创建 BidResponse
,您需要了解声明技术供应商的两种不同方式:
- 某些供应商无需声明;这些供应商已列在经过 Ad Manager 认证的外部供应商中。
- 其他供应商只有在
BidRequest
中声明后才能参与:- 在
BidRequest
中,BidRequest.imp.ext.allowed_vendor_type
字段指定卖方允许的供应商。将在allowed_vendor_type
中发送的供应商列在vendors.txt
字典文件中。
- 在
出价请求示例
以下示例展示了 Protobuf 和 JSON 请求的可读取示例。
OpenRTB Protobuf
OpenRTB JSON
如需将出价请求转换为二进制形式(就像从真实请求中的 POST 载荷中获取的一样),您可以执行以下操作(使用 C++)。不过,请注意,这不适用于 OpenRTB JSON。
string text_format_example = /* example from above */; BidRequest bid_request; if (TextFormat::ParseFromString(text_format_example, &bid_request)) { string post_payload; if (bid_request.SerializeToString(&post_payload)) { // post_payload is a binary serialization of the protocol buffer } }
实时反馈
实时反馈适用于 Authorized Buyers 买方,以及使用公开出价的广告交易平台和广告联盟。
实时反馈会根据您之前出价的一项或多项出价的结果填充 BidRequest.ext.bid_feedback
,可用于查找详细信息,例如出价是否在竞价中胜出,或在竞价中胜出所需的最低出价。如需启用实时反馈,请与您的客户经理联系。
除了在出价响应反馈中发送的默认字段之外,您还可以使用 BidResponse.seatbid.bid.ext.event_notification_token
字段在出价响应中发送自定义数据。event_notification_token
是仅供出价方知晓的任意数据,可能有助于调试,例如:代表新策略的新定位 ID 或出价 ID,或与广告素材相关联且仅供出价方知晓的元数据。如需了解详情,请参阅 OpenRTB 扩展协议缓冲区文件。
当 Authorized Buyers 向出价方发送出价请求时,出价方会回复 BidResponse
。如果出价方启用了实时反馈,那么在后续出价请求中,Authorized Buyers 会在 BidFeedback
消息中发送有关响应的反馈:
message BidFeedback { // The unique id from BidRequest.id. optional string request_id = 1; // The status code for the ad. See creative-status-codes.txt in the // technical documentation for a list of ids. optional int32 creative_status_code = 2; // Deprecated. This field is not populated and will be removed after March, // 2025. If the bid won the auction, this is the price paid in your account // currency. If the bid participated in the auction but was out-bid, this // is the CPM that should have been exceeded in order to win. This is not // set if the bid was filtered prior to the auction, if the publisher or // winning bidder has opted out of price feedback or if your account has // opted out of sharing winning prices with other bidders. For first-price // auctions, minimum_bid_to_win is populated instead of this field. optional double price = 3 [deprecated = true]; // The minimum bid value necessary to have won the auction, in your account // currency. If your bid won the auction, this is the second highest bid // that was not filtered (including the floor price). If your bid didn't win // the auction, this is the winning candidate's bid. This field will only be // populated if your bid participated in a first-price auction, and will not // be populated if your bid was filtered prior to the auction. optional double minimum_bid_to_win = 6; // The minimum bid value necessary to have won the server-side component of // the overall auction given that there was also an interest group bidding // component to the overall auction which ran using the Protected Audience // API. The value is expressed in CPM of the buyer account currency. The // minimum bid to win for the overall auction, including bids from the // server-side and the on-device interest group components, is populated in // the minimum_bid_to_win field of the same BidFeedback object. optional double sscminbidtowin = 14; // Billable event rate multiplier that was applied to this bid during // ranking. The adjustment reflects the likelihood that your bid would // generate a billable event (namely, the ad renders successfully) if it won // the auction, relative to the probability that other bids generate a // billable event if they won the auction. This adjustment can be larger or // smaller than 1. This affects the final ranking in the auction only; in // particular, this multiplier does not affect the payment or whether the // bid clears any floor price. optional float billable_event_rate_bid_adjustment = 13 [default = 1]; // When a publisher uses an RTB auction and waterfall-based SDK mediation on // the same query, the winner of the real-time auction must also compete in // a mediation waterfall (which is ordered by price) to win the impression. // If the bid participated in the auction and there was no waterfall, the // value of this field is 0. If the bid participated in the auction and // there was a waterfall, the value of this field is a price representing a // sample bid from the eligible mediation networks that were higher than the // auction winner, weighted by expected fill rate. This field can be used // in conjunction with minimum_bid_to_win to train bidding models. The CPM // is in your account currency. optional double sampled_mediation_cpm_ahead_of_auction_winner = 8; message EventNotificationToken { // The contents of the token. optional string payload = 1; } // The token included in the corresponding bid. optional EventNotificationToken event_notification_token = 4; // The creative ID included in the corresponding bid. optional string buyer_creative_id = 5; // Possible types of bid response feedback objects. enum FeedbackType { FEEDBACK_TYPE_UNSPECIFIED = 0; // Feedback for a bid that was submitted on a bid response. BID_FEEDBACK = 1; // Feedback for an interest group buyer submitted on a bid response to // particpate in an interest group bidding component of the auction run // using the Protected Audience API. INTEREST_GROUP_BUYER_FEEDBACK = 2; } // The type of the BidFeedback message. Google will send separate // BidFeedback objects for: // a) Each bid submitted on a bid response // b) Each buyer submitted on a bid response to particpate in an interest // group bidding component of the auction run using the Protected Audience // API. optional FeedbackType feedbacktype = 15; // Origin of an interest group buyer that was included in the bid response. // This field is populated only for feedback where a bidder opted in an // interest group buyer to participate in the interest group bidding // component of the overall auction run using the Protected Audience API. // To learn more about origins, see https://www.rfc-editor.org/rfc/rfc6454. // To learn more about interest group bidding and the Protected Audience // API, see // https://developers.google.com/authorized-buyers/rtb/fledge-origin-trial. optional string buyerorigin = 16; // The status code for the submitted interest group buyer. This field is // only populated in the feedback for an interest group buyer that a bidder // requested to enter into the interest group auction through the bid // response. Individual creative status codes of bids submitted by the buyer // in the on-device interest group auction are not available. See // https://storage.googleapis.com/adx-rtb-dictionaries/interest-group-buyer-status-codes.txt // for a list of interest group buyer status codes. optional int32 igbuyerstatus = 17; }
在此消息中,您应首先检查 bid_feedback.creative_status_code
字段;您可以在
creative-status-codes.txt 中找到代码含义。请注意,如果您在竞价中胜出,则可以选择不接收价格反馈。如需了解详情,请参阅如何停用。
实时反馈包含出价请求 ID 和以下任一项:
竞价结果 | 实时反馈 |
---|---|
买方未提交出价。 | 什么都不会发生。 |
买方提交的出价在进入竞价之前被滤除。 | 广告素材状态代码 (creative-status-codes.txt)。 |
买方提交了出价,但在竞价中落败。 | 广告素材状态代码 79 (竞价中出价过高)。 |
买方提交的出价赢得了竞价。 | 结算价格和广告素材状态代码 1 。
对于应用展示和广告素材状态代码为 |
示例
以下是支持的协议中显示的实时反馈示例:
OpenRTB Protobuf
OpenRTB JSON
为最高出价竞价构建出价模型
在最高出价竞价中出价后,如果出价未从竞价中滤除,您将收到实时反馈,其中包括 minimum_bid_to_win
和 sampled_mediation_cpm_ahead_of_auction_winner
字段。这些信号可用于为出价逻辑提供参考,让您了解出价可以提高或降低多少才能赢得展示机会。
minimum_bid_to_win
:能赢得实时出价竞价的最低出价。如果您赢得了竞价,则此值将是您在仍能胜出的情况下可以设置的最低出价。如果您在竞价中落败,则此出价将是胜出出价。sampled_mediation_cpm_ahead_of_auction_winner
:如果中介链中还有其他广告联盟,则此字段的值是一个价格,表示某个符合条件的中介广告联盟的出价样本,该出价高于竞价胜出方,并按预期填充率加权。如果中介链中的所有广告联盟都预计不会填充广告,或者发布商不使用 SDK 中介,则此值将设为 0。
运作方式
为了描述用于确定 minimum_bid_to_win
和 sampled_mediation_cpm_ahead_of_auction_winner
可能值的计算,我们首先需要定义以下内容:
- 以下是中介链中的 CPM,按降序排列:
\[C_1, C_2, …, C_n\]
- 以下是中介链中 CPM 的相应填充率:
\[f_1, f_2, …, f_n\]
- 以下函数用于根据给定的填充率,从中介链元素 \(i\)确定预期每千次展示费用及其概率:
\(X_i = \{C_i\) 概率为 \(f_i\); \(0\) 概率为 \(1 - f_i\}\)
- 最终胜出的中介链将如下所示:
\[\{C_1, C_2, …, C_K, W\}\]其中, \(W\) 是胜出出价, \(C_K > W >= C_{K+1}\)
- 预设价格(即底价)表示为 \(F\)。
- 次优出价记为 \(R\)。
竞价胜出者的计算
字段 | 计算 |
---|---|
minimum_bid_to_win |
\(max\{F, R, X_{K+1}, …, X_n\}\) |
sampled_mediation_cpm_ahead_ |
\(\{C_i\) 概率 \(\prod_{j=1}^{i-1}(1-f_j) \cdot f_i \div \prod_{j=1}^{K}(1-f_j)\}\)
\(1 <= i <= K\)。 |
计算竞价落败方
字段 | 计算 |
---|---|
minimum_bid_to_win |
\(max\{F, W\}\) |
sampled_mediation_cpm_ahead_ |
\(max\{X_1, …, X_K\}\) |
使用简单中介链的示例
假设发布商同时使用实时出价和 SDK 中介链,如下所示:
SDK 中介链 | 预计 CPM | 填充率 |
---|---|---|
网络 1 | \(C_1 = $3.00\) | \(f_1 = 5\%\) |
广告联盟 2 | \(C_2 = $2.00\) | \(f_2 = 45\%\) |
影音平台 3 | \(C_3 = $0.50\) | \(f_3 = 80\%\) |
影音平台 4 | \(C_4 = $0.10\) | \(f_4 = 85\%\) |
假设实时出价竞价的结果如下:
RTB 竞价 | 每千次展示费用 |
---|---|
竞价胜出者 (W) | $1.00 |
竞价亚军 (R) | $0.05 |
预订价格 / 底价 (F) | $0 |
在竞价中胜出的出价
以下示例展示了如何针对胜出的出价计算 minimum_bid_to_win
和 sampled_mediation_cpm_ahead_of_auction_winner
的值和概率。
minimum_bid_to_win |
Probability |
---|---|
\(max(F, R, C_3) = $0.50\) | \(f_3 = 80\%\) |
\(max(F, R, C_4) = $0.10\) | \((1-f_3) \cdot f_4 = 17\%\) |
\(max(F, R, 0) = $0.05\) | \((1-f_3) \cdot (1-f_4) = 3\%\) |
sampled_mediation_cpm_ |
Probability |
---|---|
\(C_1 = $3.00\) | \(f_1 \div (1-(1-f_1) \cdot (1-f_2)) =~ 10.5\%\) |
\(C_2 = $2.00\) | \(((1-f_1) \cdot f_2) \div (1-(1-f_1) \cdot (1-f_2)) =~ 89.5\%\) |
竞价失败的出价
以下示例展示了如何针对未胜出的出价计算 minimum_bid_to_win
和 sampled_mediation_cpm_ahead_of_auction_winner
的值和概率。
minimum_bid_to_win |
Probability |
---|---|
\(max(F, W) = $1.00\) | \(100\%\) |
sampled_mediation_cpm_ |
Probability |
---|---|
\(C_1 = $3.00\) | \(f_1 = 5\%\) |
\(C_2 = $2.00\) | \((1-f_1) \cdot f_2 =~ 42.8\%\) |
\(0\) | \((1-f_1) \cdot (1-f_2) =~ 52.2\%\) |
出价拆分
出价扁平化是指将单个复杂的 BidRequest
处理成发送到应用的多个出价请求。展开出价请求后,您可以确定哪些出价请求属于原始出价请求,因为它们的 BidRequest.ext.google_query_id
字段值相同。
出价扁平化功能默认处于启用状态,但如果您想停用该功能,可以与您的客户经理联系。
广告格式
某些广告展示位置可以接受多种格式。启用出价展平后,系统会通过单独的出价请求发送每种格式,其中符合条件的结算 ID 等属性与请求中指定的格式相关。
包含以下格式的出价请求将拆分为不同的出价请求:
- 横幅
- 视频
- 音频
- 原生
广告格式扁平化示例
以下示例展示了未扁平化广告格式的简化版 OpenRTB JSON 出价请求,以及一组等效的扁平化请求:
预先扁平化
扁平化后
特惠
除了公开竞价之外,给定出价方的广告机会还可适用于各种交易类型。启用按交易拆分出价功能后,系统会针对公开竞价发送一个出价请求,并针对每种类型的固定价格交易发送一个出价请求。在实践中,竞价和固定价格交易类型的广告限制可能不同。例如,对于同时可用于公开竞价和固定价格交易的给定视频广告展示机会,出价方会分别收到针对这两种交易类型的不同出价请求,其中广告时长上限和是否允许可跳过广告等限制可能不同。因此,对广告机会应用扁平化后,您可以更轻松地区分公开竞价和固定价格交易的广告约束条件。
可跳过性和视频时长
OpenRTB 规范没有单独的字段来指定可跳过式广告和不可跳过式广告的视频时长上限。Google 的实现使用出价扁平化功能,通过现有的 BidRequest.video.maxduration
和 BidRequest.video.skip
字段来区分这些广告系列。
以下示例展示了当不可跳过的广告时长上限为 15
且可跳过的广告时长上限为 60
时,视频广告资源如何展平。
示例 | max_ad_duration |
skip (true 或 false) |
---|---|---|
未展平的原始请求 | 15 |
true |
展开后的请求 1:不可跳过 | 15 |
false |
扁平化请求 2:可跳过 | 60 |
true |
只有在满足以下条件时,系统才会对可跳过的视频广告时长出价请求进行扁平化处理:
- 请求允许使用视频。
- 可跳过和不可跳过的视频广告均可投放,且这两种广告的时长上限值不同。
- 此请求符合私下竞价或公开竞价的条件。
您可以与您的技术支持客户经理联系,选择停用此类展平功能。如果停用此设置,并且发布商允许同时投放可跳过和不可跳过的视频广告,并且根据可跳过性设置不同的时长上限,skip
将设为 true
,maxduration
将设为可跳过和不可跳过的广告限制中较短的时长。
视频广告连播
包含多个广告机会的视频连播的出价请求会被拆分,以便每个出价请求都针对该连播中的单个广告机会。这样,您就可以针对给定连播的多个广告展示机会进行出价。
Open Measurement
借助 Open Measurement,您可以指定为投放到移动应用环境的广告提供独立衡量和验证服务的第三方供应商。您可以通过检查广告机会是否排除了可供发布商排除的广告素材属性中所列的 OmsdkType:
OMSDK 1.0
属性,来确定发布商是否支持出价请求中的 Open Measurement。您可以在横幅广告或视频广告的 battr
属性下找到此值,具体取决于广告格式。
如需详细了解如何解读包含公开衡量信号的出价请求,请参阅 Open Measurement SDK 帮助中心文章。
出价请求示例
以下部分显示了不同广告类型的出价请求示例。