处理请求

当 Google 向您的应用发送出价请求时,实时出价互动就开始了。本指南介绍了如何对应用进行编码,以处理出价请求。

解析请求

Google 将出价请求作为序列化协议缓冲区(附加为 HTTP POST 请求的二进制载荷)发送。Content-Type 设置为 application/octet-stream。如需查看相关示例,请参阅出价请求示例

您必须将此请求解析为 BidRequest 消息的实例。BidRequestrealtime-bidding.proto 中定义,可以从参考数据页面获取。您可以使用生成的 BidRequest 类中的 ParseFromString() 方法解析消息。例如,以下 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++ 中:

for (int i = 0; i < bid_request.adslot_size(); ++i) {
  const BidRequest_AdSlot& adslot = bid_request.adslot(i);
  // Decide what to bid on adslot.
}

BidRequest 中发送的某些信息(例如 Google 用户 ID、语言或地理位置)并非始终可用。如果您的 预定位广告组使用特定展示未知的信息,那么这些广告组将不匹配。如果缺失的信息对预定位条件无关紧要,系统在发送出价请求时会省略省略这些信息。

有关预定位广告组的信息,请查看每个 AdSlotMatchingAdData 组。其中包含提示 Google 发出出价请求的预定位广告组的第一个匹配广告组 ID,即,如果您的响应赢得针对展示机会的竞价,则需付费的广告组和广告系列。在某些情况下,您需要在 BidResponse.AdSlot 中明确指定 billing_id 以用于归因,例如当 BidRequest.AdSlot 有多个 matching_ad_data 时。如需详细了解对出价内容的限制,请参阅 realtime-bidding.proto

字典文件

出价请求会使用在字典文件中定义的标识符,您可以在参考数据页面上找到这些文件。

出价网址宏

可以选择将 BidRequest 的某些字段插入 HTTP POST 请求中使用的网址中。这在某些情况下很有用,例如,如果您使用轻量级前端,它使用请求中的值在多个后端之间进行负载均衡。如需获取有关新宏的支持,请与您的技术支持客户经理联系。

说明
%%GOOGLE_USER_ID%%

替换为 BidRequest 中的 google_user_id。例如,在请求时,出价方网址

http://google.bidder.com/path?gid=%%GOOGLE_USER_ID%%
将被替换为
http://google.bidder.com/path?gid=dGhpyBhbiBleGFtGxl
之类的网址。

如果 Google 用户 ID 未知,系统会替换空字符串,得到类似于

http://google.bidder.com/path?gid=
%%HAS_MOBILE%%

在调用 BidRequesthas_mobile() 时替换为 10

%%HAS_VIDEO%%

调用 BidRequesthas_video() 时替换为 1 (true) 或 0 (false)。

%%HOSTED_MATCH_DATA%%

替换为 BidRequest 中的 hosted_match_data 字段的值。

%%MOBILE_IS_APP%%

替换为 BidRequestmobile.is_app 字段中的 1 (true) 或 0 (false)。

从交易网址中查找移动应用 ID

移动应用交易所报告的网址如下所示:

mbappgewtimrzgyytanjyg4888888.com

使用 base-32 解码器对字符串中以粗体显示的部分 (gewtimrzgyytanjyg4888888) 进行解码。

您可以使用在线解码器,但必须将字母大写,并将尾随 8 替换为 = 值。

因此,将该值解码后:

GEWTIMRZGYYTANJYG4======
结果为:
1-429610587
字符串 429610587 是 iOS 应用的 ID iFunny

再看下面一个示例。报告的网址如下:

mbappgewtgmjug4ytmmrtgm888888.com
解码此值:
GEWTGMJUG4YTMMRTGM======
会产生以下结果:
1-314716233
结果 314716233 是 iOS 应用 TextNow 的应用 ID。

从交易网址中查找移动应用名称

以下是获取应用名称的示例。报告的网址如下所示:

mbappMFUXELTDN5WS42DZOBQWQLTJN4XHG3DJORUGK4Q888.com
对此值进行解码:
MFUXELTDN5WS42DZOBQWQLTJN4XHG3DJORUGK4Q===
会产生以下结果:
air.com.hypah.io.slither
结果相当于 Android 应用 slither.io

公开出价字段

向参与公开出价的广告交易平台和广告联盟出价方发送的出价请求与向参与标准实时出价的 Authorized Buyers 用户发送的出价请求类似。公开出价客户将会收到少量额外的字段,一些现有字段可能有替代用途。其中包括:

OpenRTB Authorized Buyers 具体说明
BidRequest.imp[].ext.dfp_ad_unit_code BidRequest.adslot[].dfp_ad_unit_code

包含发布商的 Ad Manager 广告资源网代码,后跟广告单元层次结构(用正斜线分隔)。

例如,其格式类似于 /1234/cruises/mars

BidRequest.user.data[].segment[] BidRequest.adslot[].exchange_bidding.key_value[]

从发布商发送至广告交易平台出价方的重复键值对。

您可以确定这些值是发布商发送的键值对(当 BidRequest.user.data[].name 设置为 “Publisher Passed” 时)。

声明允许的供应商

提供研究、再营销和广告投放等服务的技术供应商可能会在买方和卖方之间的互动中发挥作用。只允许经 Google 审核是否参与 Authorized Buyers 互动的供应商。

如需了解 BidRequest 并创建 BidResponse,您需要了解声明技术供应商的两种不同可能性:

  1. 有些供应商不需要声明;这些供应商会在 Authorized Buyers 帮助中列出
  2. 其他供应商只有同时在 BidRequestBidResponse 中声明的情况下才能参与测试:
    • BidRequest 中,allowed_vendor_type 字段指定卖方允许的供应商。将在 BidRequestallowed_vendor_type 字段中发送的供应商列在 Vendors.txt 字典文件中。
    • BidResponse 中,vendor_type 字段指定买方打算使用哪些获得许可的供应商。

出价请求示例

以下示例表示人类可读的 Protobuf 和 JSON 请求示例。

Google

OpenRTB JSON

OpenRTB 协议

若要将出价请求转换为二进制形式(就像您通过实际请求中的 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 在来自移动应用的出价请求中传递移动广告 ID。移动广告 ID 可以是 iOS IDFA Android 广告 ID,通过 Authorized Buyers 管理的 JavaScript 代码中的 %%EXTRA_TAG_DATA%% 宏发送。

借助 %%ADVERTISING_IDENTIFIER%% 宏,买方可以在广告展示时接收 iOS IDFA 或 Android 广告 ID。它会返回一个加密的 proto 缓冲区 MobileAdvertisingId,如 %%EXTRA_TAG_DATA%%

message MobileAdvertisingId {
  optional bytes advertising_id = 1;
  optional int32 user_id_type = 2;
}

user_id_type 是在 enum AdxMobileIdType 中定义的值之一:

enum AdxMobileIdType {
  MOBILE_ID_UNKNOWN = 0,
  IDFA = 1,
  ANDROID_ID = 2,
};

您可以使用在广告展示呈现期间收集的广告 ID,根据移动广告 ID 创建用户名单。这些用户名单可以保存在您的服务器上,也可以存放在我们的服务器上。要在 Google 服务器上创建用户名单,您可以使用我们的批量上传工具。

当移动广告 ID 与某个用户列表匹配时,您就可以使用它来进行再营销。

实时反馈

Authorized Buyers 以及使用公开出价的广告交易平台和广告联盟都可以获取实时反馈。

AdX 协议和 OpenRTB 的后续出价请求均支持出价响应反馈。对于 OpenRTB,则会在 BidRequestExt 中发送。

除了出价响应反馈中发送的默认字段之外,您还可以使用 BidResponse 中返回的 event_notification_token(在 AdX Proto 或 OpenRTB 中)在出价响应中发送自定义数据。event_notification_token 是只有出价方知道并且可能有助于调试的任意数据,例如:代表新策略的新定位 ID 或出价 ID,或与只有出价方知道的广告素材相关联的元数据。如需了解详情,请参阅适用于 RTB 的 OpenRTB Extensions Protocol Buffer 和适用于 AdX 的 AdX Proto

当 Authorized Buyers 向出价方发送出价请求时,该出价方会回复 BidResponse。如果出价方启用了实时反馈功能,那么在后续出价请求中,Authorized Buyers 会在 BidResponseFeedback 消息中发送对该响应的反馈,如下所示:

message BidResponseFeedback {
  // The unique id from BidRequest.id
  optional bytes request_id = 1;

  // The index of the BidResponse_Ad if there was more than one. The index
  // starts at zero for the first creative.
  optional int32 creative_index = 2;

  // 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 = 3;

  // 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 int64 cpm_micros = 4;

  // The minimum bid value necessary to have won the auction, in micros of
  // 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 did not 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 int64 minimum_bid_to_win = 7;

  // 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 micros 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 BidResponseFeedback object.
  optional int64 server_side_component_minimum_bid_to_win = 16;

  // 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 = 15 [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 micros of your account currency.
  optional int64 sampled_mediation_cpm_ahead_of_auction_winner = 10;

  // Event notification token that was included in the bid response.
  optional bytes event_notification_token = 5;

  // Buyer creative ID that was included in the bid response.
  optional string buyer_creative_id = 6;

  // 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 BidResponseFeedback message. Google will send separate
  // BidResponseFeedback 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 feedback_type = 17;

  // 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 buyer_origin = 18;

  // 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 interest_group_buyer_status_code = 19;
}

在此消息中,您应检查的第一个字段是 bid_response_feedback.creative_status_code;您可以在 creative-status-codes.txt 中找到代码的含义。请注意,如果您赢得出价,可以选择退出价格反馈。如需了解详情,请参阅如何选择退出

实时反馈包括出价请求 ID 和以下某一项:

竞价结果 实时反馈
买方未提交出价。 什么都不会发生。
买方提交的出价在进入竞价流程之前就已被滤除。 广告素材状态代码 (creative-status-codes.txt)。
买方提交了出价,但在竞价中落败。 广告素材状态代码 79(在竞价中出价过低)。
买方提交了在竞价中胜出的出价。 清算价格和广告素材状态代码 1

对于应用展示且广告素材状态代码为 83,应用发布商可能已经在使用中介广告瀑布流,因此胜出的出价会与发布商回传广告瀑布流链中的其他需求展开竞争。了解如何在出价时使用 sampled_mediation_cpm_ahead_of_auction_winner

示例

以下是支持的协议中显示的实时反馈示例:

Google

OpenRTB JSON

OpenRTB 协议

构建最高出价竞价出价模型

在最高出价竞价机制中出价后,您会收到包含 minimum_bid_to_winsampled_mediation_cpm_ahead_of_auction_winner 字段的实时反馈(如果出价未在竞价中被滤除)。这些信号可用于告知您的出价逻辑,为了赢得展示机会,您的出价应该提高或降低多少。

  • minimum_bid_to_win:为赢得实时出价竞价而可能给出的最低出价。如果您在竞价中胜出,那么这将是您在胜出时原本可以给出的最低出价。如果在竞价中落败,该出价将会是胜出的出价。
  • sampled_mediation_cpm_ahead_of_auction_winner:如果中介链中有其他广告联盟,则此字段的值是一个价格,代表高于竞价胜出者的某个符合条件的中介广告联盟的某个示例出价(按预期填充率进行加权)。如果中介链中没有预计会填充的广告联盟,或者发布商未使用 SDK 中介,则此值设置为 0。

运作方式

为了描述用于确定 minimum_bid_to_winsampled_mediation_cpm_ahead_of_auction_winner 可能值的计算,我们首先需要定义以下内容:

  • 下表按降序显示了中介链中的 CPM:
    \[C_1, C_2, …, C_n\]
  • 下面显示了中介链中 CPM 的相应填充率:
    \[f_1, f_2, …, f_n\]
  • 以下函数用于根据指定的填充率,确定中介链元素 \(i\)的预期 CPM 及其概率:
    \(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_
of_auction_winner
\(\{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_
of_auction_winner
\(max\{X_1, …, X_K\}\)

简单中介链示例

假设发布商同时使用实时出价和 SDK 中介链,如下所示:

SDK 中介链 预计每千次展示费用 填充率
网络 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_winsampled_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_
ahead_of_auction_winner
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_winsampled_mediation_cpm_ahead_of_auction_winner 的值和概率。

minimum_bid_to_win Probability
\(max(F, W) = $1.00\) \(100\%\)
sampled_mediation_cpm_
ahead_of_auction_winner
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 处理成多个发送到您应用的出价请求的过程。由于它们保留相同的 ID(Authorized Buyers RTB 协议中的 BidRequest.google_query_id 或 OpenRTB 协议中的 BidRequestExt.google_query_id),因此您可以在拆分后确定哪些出价请求相关。

广告格式

某些广告机会可接受多种格式。通过出价拆分,每种格式都将在不同的出价请求中发送,其中符合条件的结算 ID 等属性与请求中指定的格式相关。

包含以下格式的出价请求会被拆分为不同的出价请求:

  • 横幅
  • 视频
  • 音频
  • 原生

广告格式展平示例

下例展示了未采用广告格式扁平化的简化 OpenRTB JSON 出价请求,而不是与之对应的一组扁平化请求:

预扁平化

后扁平化

特惠

除了公开竞价之外,给定出价方的广告机会还适用于各种交易类型。通过按交易拆分出价,系统会为公开竞价发送一个出价请求,并针对每种固定价格交易发送一个出价请求。实际上,竞价和固定价格交易类型的广告限制条件可能有所不同。例如,对于同时适用于公开竞价和固定价格交易的给定视频广告机会,出价工具将收到不同的出价请求,对于这两种交易,广告时长上限和是否允许可跳过式广告等限制条件都可能会有所不同。因此,通过对广告机会应用展平,您可以更轻松地辨别公开竞价和固定价格交易的广告限制条件。

可跳过式视频广告时长上限

Google 的协议和 OpenRTB 实现支持以下有关视频时长和可跳过性的字段:

时长 可跳过时长 是否可跳过
Google 协议 max_ad_duration skippable_max_ad_duration video_ad_skippable
OpenRTB maxduration 不适用 skip

这意味着,虽然 Google 协议可以设置可跳过和不可跳过的精细时长,但 OpenRTB 实现只有一个时长上限值。

在拆分出价之前,OpenRTB 的 maxduration 会被设置为 Google 协议的 max_ad_durationskippable_max_ad_duration 字段中较低的值。当这些值不同时,此行为现已更改为发送两个单独的出价请求:一个代表 maxduration(代表可跳过的广告),另一个代表不可跳过的广告展示机会。

以下示例展示了在拆分出价之前和之后,Google 协议请求如何转换为 OpenRTB。等效 Google 协议请求的 max_ad_duration15skippable_max_ad_duration60

示例 max_ad_duration skip(true 或 false)
未拆分的原始请求 15 true
拆分请求 1:不可跳过 15 false
拆分请求 2:可跳过 60 true

仅当满足以下条件时,系统才会对可跳过式视频广告时长出价请求进行扁平化处理:

  • 请求允许播放视频。
  • 允许展示跳过视频和不跳过视频广告,且这两个时长上限的值有所不同。
  • 此请求符合私下竞价或公开竞价的条件。
  • 出价方帐号具有有效的 OpenRTB 端点。

如需选择停用此类拆分操作,请与您的技术支持客户经理联系。

视频广告连播

对于具有多个广告机会的视频广告连播,系统会拆分出价请求,以确保每个出价请求都针对该广告连播中的单个广告机会。这样,您就可以在指定的广告连播中针对多个广告机会进行出价。

开放式衡量

借助 Open Measurement,您可以指定第三方供应商,这些供应商可以为在移动应用环境中投放的广告提供独立的衡量和验证服务。

您可以检查广告机会是否排除了发布商可排除的广告素材属性中的 OmsdkType: OMSDK 1.0 属性,从而确定发布商是否在出价请求中支持 Open Measurement。对于 Authorized Buyers 协议,此参数位于 BidRequest.adslot[].excluded_attribute 下。对于 OpenRTB 协议,此参数位于横幅广告视频广告battr 属性下,具体取决于格式。

如需详细了解如何解读包含 Open Measurement 信号的出价请求,请参阅 Open Measurement SDK 帮助中心文章。

出价请求示例

以下各部分展示了不同广告类型的出价请求示例。

应用横幅广告

Google

OpenRTB JSON

OpenRTB 协议

应用(插页式)

Google

OpenRTB JSON

OpenRTB 协议

应用插页式视频广告

Google

OpenRTB 协议

应用原生

Google

OpenRTB JSON

OpenRTB 协议

网络视频

Google

广告交易平台出价工具的移动网站横幅

OpenRTB 协议